{
  "commit": "c8b1758f1d6b4287dcc7ed8faa4ae165a4668c51",
  "extensions": [
    {
      "name": "2048",
      "kind": "registry",
      "title": "2048",
      "description": "The sliding-tile game in the panel, played from the keyboard. The board and your best score are kept across restarts, and on every machine you sign in on.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M2 2h5.5v5.5H2zM8.5 2H14v5.5H8.5zM2 8.5h5.5V14H2zM8.5 8.5H14V14H8.5z",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/2048@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/2048",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "2048",
        "title": "2048",
        "description": "The sliding-tile game in the panel, played from the keyboard. The board and your best score are kept across restarts, and on every machine you sign in on.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M2 2h5.5v5.5H2zM8.5 2H14v5.5H8.5zM2 8.5h5.5V14H2zM8.5 8.5H14V14H8.5z",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "undo",
            "label": "Undo",
            "text": "U takes the last move back",
            "description": "One move only; taking a win back restores the banner. Off, the key does nothing and the move is not listed.",
            "default": true
          }
        ],
        "sync": {
          "game": "latest",
          "best": "max",
          "top": "max",
          "games": "sum"
        },
        "leaderboards": [
          {
            "id": "score",
            "title": "Best score",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 4000000
          },
          {
            "id": "tile",
            "title": "Highest tile",
            "order": "desc",
            "format": "points",
            "min": 2,
            "max": 131072
          }
        ],
        "store": {
          "tagline": "2048 in the panel, keyboard only; the board persists",
          "category": "fun",
          "features": [
            "Arrows or `hjkl` slide the tiles; the score leads above the board, the best and the move count beside it",
            "The classic rules: equal tiles merge once per move, a new 2 or 4 lands after every move",
            "Tiles slide, merge and pop in, coloured by value",
            "`U` takes a move back (a setting); `N` starts over, asking first mid-game",
            "Keep going past 2048, or start a new game",
            "Leave with `escape` any time; the board, score and best score are there when you come back",
            "Signed in to a pal account, the board and your best follow you to every machine; each finished game's score and highest tile go on the leaderboards"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-board.png",
              "caption": "Mid-game: the score leads, the best and the move count beside it, the keys under the board",
              "cover": [
                438,
                252,
                560,
                275
              ]
            },
            {
              "file": "2-won.png",
              "caption": "The first 2048: keep going or start over"
            },
            {
              "file": "3-over.png",
              "caption": "Game over: no move left, the score, Enter for a new game"
            }
          ],
          "actions": [
            {
              "title": "Up, Down, Left, Right",
              "description": "Slide every tile that way; equal neighbours merge. `k`, `j`, `h`, `l` too.",
              "keys": "up, down, left, right"
            },
            {
              "title": "Undo the last move",
              "description": "One move back, when the `undo` setting is on.",
              "keys": "u"
            },
            {
              "title": "New game",
              "description": "A fresh board; asks first mid-game, where Enter is this too. The best score is kept.",
              "keys": "n"
            },
            {
              "title": "Keep going",
              "description": "After the first 2048, play on for a higher tile.",
              "keys": "enter"
            },
            {
              "title": "Sign in",
              "description": "At game over while signed out: opens Settings › Account, so your scores are kept with your account.",
              "keys": "s"
            }
          ]
        },
        "palettes": {
          "2048": {
            "title": "2048",
            "kind": "view",
            "description": "The board. Escape leaves mid-game; it is there when you come back.",
            "keys": [
              {
                "keys": "up",
                "title": "Move (also down, left, right, and hjkl)"
              },
              {
                "keys": "u",
                "title": "Undo the last move"
              },
              {
                "keys": "n",
                "title": "New game"
              },
              {
                "keys": "enter",
                "title": "New game (asks mid-game); Keep going after the first 2048"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/2048",
      "tagline": "2048 in the panel, keyboard only; the board persists",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/2048/screenshots/1-board-dark.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/1-board.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/2-won-dark.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/2-won.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/3-over-dark.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/3-over.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/2048/screenshots/1-board.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/2-won.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/3-over.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/2048/screenshots/1-board-dark.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/2-won-dark.png",
        "https://pal.cagdas.io/extensions/2048/screenshots/3-over-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "appletv",
      "kind": "registry",
      "title": "Apple TV",
      "description": "A remote for your Apple TV under the keys: the clickpad on the arrows, Now Playing in full with chapters, subtitles, Up Next and lyrics, links played on the TV in one key (copy a YouTube link and pal offers it), your apps a digit away, typing into the TV's search from the keyboard, sleep and wake, users, and the menu bar. Pairs in a guided setup, no other app or hub needed.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M20.57 17.735h-1.815l-3.34-9.203h1.633l2.02 5.987c.075.231.273.9.586 2.012l.297-.997.33-1.006 2.094-6.004H24zm-5.344-.066a5.76 5.76 0 0 1-1.55.207c-1.23 0-1.84-.693-1.84-2.087V9.646h-1.063V8.532h1.121V7.081l1.476-.602v2.062h1.707v1.113H13.38v5.805c0 .446.074.75.214.932.14.182.396.264.75.264.207 0 .495-.041.883-.115zm-7.29-5.343c.017 1.764 1.55 2.358 1.567 2.366-.017.042-.248.842-.808 1.658-.487.71-.99 1.418-1.79 1.435-.783.016-1.03-.462-1.93-.462-.89 0-1.17.445-1.913.478-.758.025-1.344-.775-1.838-1.484-.998-1.451-1.765-4.098-.734-5.88.51-.89 1.426-1.451 2.416-1.46.75-.016 1.468.512 1.93.512.461 0 1.327-.627 2.234-.536.38.016 1.452.157 2.136 1.154-.058.033-1.278.743-1.27 2.219M6.468 7.988c.404-.495.685-1.18.61-1.864-.585.025-1.294.388-1.723.883-.38.437-.71 1.138-.619 1.806.652.05 1.328-.338 1.732-.825Z",
          "box": 24,
          "bg": "#000000"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/appletv@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/appletv",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "appletv",
        "title": "Apple TV",
        "description": "A remote for your Apple TV under the keys: the clickpad on the arrows, Now Playing in full with chapters, subtitles, Up Next and lyrics, links played on the TV in one key (copy a YouTube link and pal offers it), your apps a digit away, typing into the TV's search from the keyboard, sleep and wake, users, and the menu bar. Pairs in a guided setup, no other app or hub needed.",
        "keywords": [
          "atv",
          "tv",
          "remote",
          "appletv"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M20.57 17.735h-1.815l-3.34-9.203h1.633l2.02 5.987c.075.231.273.9.586 2.012l.297-.997.33-1.006 2.094-6.004H24zm-5.344-.066a5.76 5.76 0 0 1-1.55.207c-1.23 0-1.84-.693-1.84-2.087V9.646h-1.063V8.532h1.121V7.081l1.476-.602v2.062h1.707v1.113H13.38v5.805c0 .446.074.75.214.932.14.182.396.264.75.264.207 0 .495-.041.883-.115zm-7.29-5.343c.017 1.764 1.55 2.358 1.567 2.366-.017.042-.248.842-.808 1.658-.487.71-.99 1.418-1.79 1.435-.783.016-1.03-.462-1.93-.462-.89 0-1.17.445-1.913.478-.758.025-1.344-.775-1.838-1.484-.998-1.451-1.765-4.098-.734-5.88.51-.89 1.426-1.451 2.416-1.46.75-.016 1.468.512 1.93.512.461 0 1.327-.627 2.234-.536.38.016 1.452.157 2.136 1.154-.058.033-1.278.743-1.27 2.219M6.468 7.988c.404-.495.685-1.18.61-1.864-.585.025-1.294.388-1.723.883-.38.437-.71 1.138-.619 1.806.652.05 1.328-.338 1.732-.825Z",
            "box": 24,
            "bg": "#000000"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "suggests": [
          "samsungtv"
        ],
        "settings": [
          {
            "kind": "text",
            "id": "device",
            "label": "Apple TV",
            "placeholder": "Living Room",
            "description": "Which paired Apple TV the remote, the root commands and the bar item control, by its name. Empty: the one paired last. d on the remote switches, and writes it here.",
            "default": ""
          },
          {
            "kind": "list",
            "id": "favorites",
            "label": "Dock",
            "placeholder": "An app's name (YouTube) or bundle id",
            "description": "The apps on the remote's dock, in order; each gets a digit, 1 to 8. Empty: the apps you open most. cmd+D in Apple TV Apps adds or removes one.",
            "default": []
          },
          {
            "kind": "number",
            "id": "skip",
            "label": "Skip",
            "description": "How far , and . (and Skip Back / Forward at the root) move what plays.",
            "min": 5,
            "max": 60,
            "step": 5,
            "unit": "s",
            "default": 10
          },
          {
            "kind": "boolean",
            "id": "wake",
            "label": "Wake",
            "text": "Wake the Apple TV when the remote opens",
            "description": "With HDMI-CEC on, the TV set comes on with it.",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "stay",
            "label": "Stay connected",
            "text": "Keep the connection open in the background",
            "description": "So the menu bar item follows what plays and a key answers at once. Off, pal connects while the remote is open and lets go a minute and a half after.",
            "default": true
          }
        ],
        "palettes": {
          "remote": {
            "title": "Apple TV Remote",
            "description": "The clickpad on the arrows, Enter selects, Backspace goes back, the TV button on h; what is playing with its cover and a seek bar, the volume, your dock of apps on the digits, and a field that types into the TV.",
            "kind": "view",
            "keywords": [
              "clickpad",
              "control"
            ],
            "refresh": 15,
            "on": [
              "wake",
              "network",
              "show"
            ],
            "keys": [
              {
                "keys": "up, down, left, right",
                "title": "Move (the clickpad)"
              },
              {
                "keys": "shift+up, shift+down, shift+left, shift+right",
                "title": "Swipe"
              },
              {
                "keys": "enter",
                "title": "Select"
              },
              {
                "keys": "shift+enter",
                "title": "Hold Select: more options"
              },
              {
                "keys": "backspace",
                "title": "Back"
              },
              {
                "keys": "h",
                "title": "Home, the TV button"
              },
              {
                "keys": "tab",
                "title": "App switcher"
              },
              {
                "keys": "c",
                "title": "Control Center"
              },
              {
                "keys": "space",
                "title": "Play or pause"
              },
              {
                "keys": ", .",
                "title": "Skip back or forward"
              },
              {
                "keys": "cmd+left, cmd+right",
                "title": "Previous or next (chapter, track)"
              },
              {
                "keys": "- =",
                "title": "Volume down or up"
              },
              {
                "keys": "1-8",
                "title": "Open a dock app"
              },
              {
                "keys": "n",
                "title": "Now Playing"
              },
              {
                "keys": "l",
                "title": "Play the link just copied (or pick one)"
              },
              {
                "keys": "a",
                "title": "All apps"
              },
              {
                "keys": "t",
                "title": "Type into the field the TV shows"
              },
              {
                "keys": "p",
                "title": "Sleep or wake"
              },
              {
                "keys": "s",
                "title": "Screen saver"
              },
              {
                "keys": "u",
                "title": "Switch user"
              },
              {
                "keys": "d",
                "title": "Switch Apple TV (with several paired)"
              },
              {
                "keys": "b",
                "title": "Next sound output (when the group's TV serves them)"
              },
              {
                "keys": "shift+s",
                "title": "Reconnect sound (when the group's TV offers it)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy what is playing"
              },
              {
                "keys": "r",
                "title": "Reconnect"
              }
            ]
          },
          "now": {
            "title": "Now Playing on Apple TV",
            "description": "What plays on the Apple TV in full: the cover with its colour behind it, the show, season and episode or the artist, the synopsis, a position bar split at the chapters, hold-to-scrub, speed, subtitles and audio, and a panel for Up Next, Chapters, Audio, Subtitles, Lyrics and Info.",
            "kind": "view",
            "keywords": [
              "playing",
              "up next",
              "queue",
              "chapters",
              "subtitles",
              "lyrics"
            ],
            "refresh": 15,
            "on": [
              "wake",
              "network",
              "show"
            ],
            "keys": [
              {
                "keys": "space",
                "title": "Play or pause"
              },
              {
                "keys": "left, right",
                "title": "Scrub: hold to go faster, one seek when you let go"
              },
              {
                "keys": "shift+left, shift+right",
                "title": "Scrub by the minute"
              },
              {
                "keys": ", .",
                "title": "Skip back or forward"
              },
              {
                "keys": "cmd+left, cmd+right",
                "title": "Previous or next (chapter, episode, track)"
              },
              {
                "keys": "tab",
                "title": "Next panel: Up Next, Chapters, Audio, Subtitles, Lyrics, Info"
              },
              {
                "keys": "q c a s y i",
                "title": "Open a panel"
              },
              {
                "keys": "up, down, enter",
                "title": "Walk the panel; play, jump or choose"
              },
              {
                "keys": "[ ]",
                "title": "Slower or faster"
              },
              {
                "keys": "l",
                "title": "Like (music)"
              },
              {
                "keys": "cmd+s, cmd+r",
                "title": "Shuffle, repeat"
              },
              {
                "keys": "- =",
                "title": "Volume"
              },
              {
                "keys": "o",
                "title": "The remote"
              },
              {
                "keys": "cmd+c",
                "title": "Copy what is playing"
              }
            ]
          },
          "play": {
            "title": "Play on Apple TV",
            "description": "Send a link to the TV in one key: a YouTube video (at its start time), a Netflix title or an Apple TV+ page. Lists the link just copied, the browser tab in front (a YouTube video from where it is in the tab, which pauses as the TV takes over), every link in the clipboard history and what was played before; a link typed or pasted at the root is offered there too.",
            "kind": "input",
            "keywords": [
              "youtube",
              "netflix",
              "link",
              "url",
              "cast",
              "send"
            ],
            "match": "https?://\\S*(youtu\\.?be|netflix\\.com/(title|watch)|tv\\.apple\\.com)",
            "inline": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Play on the TV"
              },
              {
                "keys": "cmd+enter",
                "title": "Play from the start (a link with a start time)"
              },
              {
                "keys": "cmd+o",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "apps": {
            "title": "Apple TV Apps",
            "description": "Every app on the Apple TV with its icon; Enter opens it on the TV.",
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open on the TV"
              },
              {
                "keys": "cmd+enter",
                "title": "Open, then show the remote"
              },
              {
                "keys": "cmd+d",
                "title": "Add to or remove from the dock"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the bundle id"
              }
            ]
          },
          "commands": {
            "title": "Apple TV",
            "description": "Play or pause, sleep, wake, home, Control Center, the screen saver, skip, volume, typing and switching users or Apple TVs, as root results.",
            "kind": "list",
            "tier": "primary",
            "keys": [
              {
                "keys": "enter",
                "title": "Run"
              },
              {
                "keys": "tab",
                "title": "On Type on Apple TV: the text to type"
              }
            ]
          },
          "users": {
            "title": "Apple TV Users",
            "description": "The people signed in on the Apple TV; Enter switches to one.",
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Switch to this user"
              }
            ]
          },
          "setup": {
            "title": "Set Up Apple TV",
            "description": "Finds the Apple TVs on the network and pairs one in two codes: the remote, then what is playing (skippable); ends with a check of what works.",
            "kind": "view",
            "keywords": [
              "pair"
            ],
            "keys": [
              {
                "keys": "1-9",
                "title": "Pair with that Apple TV"
              },
              {
                "keys": "enter",
                "title": "Send the code"
              },
              {
                "keys": "n",
                "title": "Show a new code"
              },
              {
                "keys": "s",
                "title": "Skip the now playing step"
              },
              {
                "keys": "i",
                "title": "Type an address"
              },
              {
                "keys": "r",
                "title": "Look again"
              },
              {
                "keys": "x",
                "title": "Forget an Apple TV"
              }
            ]
          }
        },
        "bar": {
          "playing": {
            "title": "Apple TV",
            "description": "What plays on the Apple TV, hidden while nothing does; a link just copied brings it up for a minute and a half to offer it. The popover is the remote: what plays, the clickpad and the buttons, the dock on the digits, the copied link on l.",
            "refresh": {
              "every": 60,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "keys": [
              {
                "keys": "up, down, left, right",
                "title": "Move"
              },
              {
                "keys": "enter",
                "title": "Select"
              },
              {
                "keys": "backspace",
                "title": "Back"
              },
              {
                "keys": "h",
                "title": "Home"
              },
              {
                "keys": "space",
                "title": "Play or pause"
              },
              {
                "keys": ", .",
                "title": "Skip back or forward"
              },
              {
                "keys": "- =",
                "title": "Volume"
              },
              {
                "keys": "1-6",
                "title": "Open a dock app"
              },
              {
                "keys": "t",
                "title": "Type into the TV"
              },
              {
                "keys": "p",
                "title": "Sleep or wake"
              },
              {
                "keys": "l",
                "title": "Play the copied link"
              },
              {
                "keys": "n",
                "title": "Now Playing"
              }
            ],
            "rules": [
              {
                "id": "paused",
                "when": "appletv.power == 'on' and not appletv.playing and appletv.title",
                "description": "Something is loaded but paused: muted on the strip.",
                "color": "muted"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "when",
                "label": "Show",
                "description": "While something plays (paused counts), or whenever the Apple TV is awake (the app in front then).",
                "options": [
                  {
                    "id": "playing",
                    "title": "While something plays"
                  },
                  {
                    "id": "awake",
                    "title": "While the Apple TV is awake"
                  }
                ],
                "default": "playing"
              },
              {
                "kind": "boolean",
                "id": "artwork",
                "label": "Icon",
                "text": "The app's icon instead of the TV mark",
                "default": false,
                "description": "Off, the strip keeps the TV mark like the menu bar's other glyphs; on, the App Store icon with rounded corners."
              }
            ],
            "mocks": {
              "playing": {
                "title": "A film playing",
                "item": {
                  "icon": "󰔂",
                  "title": "The Long Quiet",
                  "tooltip": "The Long Quiet · TV on Living Room"
                }
              },
              "paused": {
                "title": "Paused",
                "item": {
                  "icon": "󰔂",
                  "title": "The Long Quiet",
                  "color": "muted",
                  "tooltip": "The Long Quiet · TV on Living Room, paused"
                }
              },
              "asleep": {
                "title": "Asleep or nothing playing",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰔂",
                    "tooltip": "Living Room is asleep"
                  }
                }
              }
            }
          }
        },
        "states": {
          "power": {
            "description": "The Apple TV's power: on, off, screensaver, unknown",
            "kind": "string"
          },
          "playing": {
            "description": "Something is playing on the Apple TV",
            "kind": "boolean"
          },
          "app": {
            "description": "The app in front on the Apple TV",
            "kind": "string"
          },
          "title": {
            "description": "The title of what plays on the Apple TV",
            "kind": "string"
          }
        },
        "links": {
          "key": {
            "description": "Press a remote button",
            "params": {
              "name": {
                "description": "up, down, left, right, select, menu, home, play_pause, volume_up, volume_down, sleep, wake, screensaver",
                "required": true
              },
              "press": {
                "description": "tap (default), double or hold"
              }
            }
          },
          "launch": {
            "description": "Open an app on the Apple TV",
            "params": {
              "app": {
                "description": "Its name (YouTube), bundle id, or a url the app handles",
                "required": true
              }
            }
          },
          "power": {
            "description": "Wake the Apple TV or put it to sleep",
            "params": {
              "to": {
                "description": "on, off or toggle (default)"
              }
            }
          },
          "type": {
            "description": "Type into the text field the Apple TV shows",
            "params": {
              "text": {
                "description": "The text",
                "required": true
              },
              "append": {
                "description": "Add to what is there instead of replacing it",
                "type": "boolean"
              }
            }
          },
          "media": {
            "description": "A transport command",
            "params": {
              "command": {
                "description": "play_pause, play, pause, next, previous, skip_forward, skip_backward, seek",
                "required": true
              },
              "value": {
                "description": "Seconds: how far to skip, or where to seek",
                "type": "number"
              }
            }
          },
          "volume": {
            "description": "The volume, as the TV set reports it over HDMI-CEC",
            "params": {
              "level": {
                "description": "up, down, or 0 to 100",
                "required": true
              }
            }
          },
          "play": {
            "description": "Play a link on the Apple TV: the url given, else the link just copied, else the browser tab in front",
            "params": {
              "url": {
                "description": "A YouTube or Netflix link, or an Apple TV+ page"
              }
            }
          }
        },
        "store": {
          "tagline": "Your Apple TV's remote, Now Playing and links, from the keyboard",
          "category": "media",
          "features": [
            "The clickpad on the arrows, Enter selects, Backspace goes back, h is the TV button; swipes on shift and the arrows",
            "Now Playing in full: the cover's colour behind it, chapters on the position bar, hold-to-scrub, speed, subtitles and audio, Up Next, lyrics",
            "Play a link on the TV in one key: copy a YouTube link and pal offers it, or paste one at the root",
            "The YouTube video in your browser carries on on the TV from where you were, and the tab pauses (Chrome with its DevTools port on; Browser Tabs' rows offer it too)",
            "Your dock of apps on the digits, drawn as the TV's own tvOS icons; every app at the root: type `youtube`, press Enter",
            "Type into the TV's search from the keyboard instead of hunting letters on screen",
            "Sleep and wake, Control Center, the app switcher, the screen saver, switching users",
            "A menu bar item with what plays; its popover is the remote",
            "Guided setup: finds the Apple TV, takes the code it shows, and checks what works",
            "In a group with your TV (Settings › Groups), the remote sets the TV's volume, switches its inputs, moves its sound (b, shift+S reconnects a soundbar) and wakes both",
            "With Samsung TV installed too, o opens the TV's own remote over this one (its settings, its sound) and Escape comes back"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-now.png",
              "caption": "Now Playing: the episode on its own colour, the chapters on the position bar, speed, subtitles and audio, Up Next with its stills"
            },
            {
              "file": "2-remote.png",
              "caption": "The remote: the clickpad and the buttons, what plays, your apps as the TV draws them on the digits, the volume"
            },
            {
              "file": "3-play.png",
              "caption": "Play on Apple TV: the link just copied, the browser tab in front and every link copied before; Enter plays it on the TV"
            },
            {
              "file": "4-offer.png",
              "caption": "Copy a YouTube link and the remote offers it: l plays it on the TV, at its start time"
            },
            {
              "file": "5-lyrics.png",
              "caption": "A song with its lyrics, the line playing lit; hold an arrow to scrub, one seek when you let go"
            },
            {
              "file": "6-setup.png",
              "caption": "Guided setup: type the code the TV shows; a second code adds what is playing"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: what plays on the Apple TV",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the remote: what plays with its seek bar, the clickpad and the buttons, the dock on the digits",
              "kind": "bar",
              "box": [
                352,
                64,
                840,
                934
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the TV mark and the title",
              "kind": "bar"
            }
          ]
        },
        "controls": [
          "volume",
          "power",
          "player"
        ]
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/appletv",
      "tagline": "Your Apple TV's remote, Now Playing and links, from the keyboard",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/appletv/screenshots/1-now-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/1-now.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/2-remote-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/2-remote.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/3-play-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/3-play.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/4-offer-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/4-offer.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/5-lyrics-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/5-lyrics.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/6-setup-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/6-setup.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/appletv/screenshots/1-now.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/2-remote.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/3-play.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/4-offer.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/5-lyrics.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/6-setup.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/appletv/screenshots/1-now-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/2-remote-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/3-play-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/4-offer-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/5-lyrics-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/6-setup-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/appletv/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "playing",
          "title": "Apple TV",
          "description": "What plays on the Apple TV, hidden while nothing does; a link just copied brings it up for a minute and a half to offer it. The popover is the remote: what plays, the clickpad and the buttons, the dock on the digits, the copied link on l.",
          "refresh": {
            "every": 60,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "key",
          "url": "pal://appletv/key?name=\u003cname\u003e",
          "cli": "pal call appletv/key name=\u003cname\u003e",
          "description": "Press a remote button",
          "params": [
            {
              "name": "name",
              "description": "up, down, left, right, select, menu, home, play_pause, volume_up, volume_down, sleep, wake, screensaver",
              "required": true
            },
            {
              "name": "press",
              "description": "tap (default), double or hold"
            }
          ]
        },
        {
          "route": "launch",
          "url": "pal://appletv/launch?app=\u003capp\u003e",
          "cli": "pal call appletv/launch app=\u003capp\u003e",
          "description": "Open an app on the Apple TV",
          "params": [
            {
              "name": "app",
              "description": "Its name (YouTube), bundle id, or a url the app handles",
              "required": true
            }
          ]
        },
        {
          "route": "power",
          "url": "pal://appletv/power",
          "cli": "pal call appletv/power",
          "description": "Wake the Apple TV or put it to sleep",
          "params": [
            {
              "name": "to",
              "description": "on, off or toggle (default)"
            }
          ]
        },
        {
          "route": "type",
          "url": "pal://appletv/type?text=\u003ctext\u003e",
          "cli": "pal call appletv/type text=\u003ctext\u003e",
          "description": "Type into the text field the Apple TV shows",
          "params": [
            {
              "name": "text",
              "description": "The text",
              "required": true
            },
            {
              "name": "append",
              "description": "Add to what is there instead of replacing it",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "media",
          "url": "pal://appletv/media?command=\u003ccommand\u003e",
          "cli": "pal call appletv/media command=\u003ccommand\u003e",
          "description": "A transport command",
          "params": [
            {
              "name": "command",
              "description": "play_pause, play, pause, next, previous, skip_forward, skip_backward, seek",
              "required": true
            },
            {
              "name": "value",
              "description": "Seconds: how far to skip, or where to seek",
              "type": "number"
            }
          ]
        },
        {
          "route": "volume",
          "url": "pal://appletv/volume?level=\u003clevel\u003e",
          "cli": "pal call appletv/volume level=\u003clevel\u003e",
          "description": "The volume, as the TV set reports it over HDMI-CEC",
          "params": [
            {
              "name": "level",
              "description": "up, down, or 0 to 100",
              "required": true
            }
          ]
        },
        {
          "route": "play",
          "url": "pal://appletv/play",
          "cli": "pal call appletv/play",
          "description": "Play a link on the Apple TV: the url given, else the link just copied, else the browser tab in front",
          "params": [
            {
              "name": "url",
              "description": "A YouTube or Netflix link, or an Apple TV+ page"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "apps",
      "kind": "bundled",
      "title": "Applications",
      "description": "Launch any installed app by name, with its own icon. On macOS, running apps can be quit or hidden and the System Settings panes are rows too; on Linux, an app's own actions are one key away.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰀻",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/apps@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/apps",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "apps",
        "title": "Applications",
        "description": "Launch any installed app by name, with its own icon. On macOS, running apps can be quit or hidden and the System Settings panes are rows too; on Linux, an app's own actions are one key away.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰀻",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "list",
            "id": "folders",
            "local": true,
            "label": "Extra folders",
            "description": "Scanned in addition to the system's application folders.",
            "placeholder": "/path/to/apps",
            "default": []
          }
        ],
        "store": {
          "tagline": "Every installed app, with its icon, a keystroke from launch",
          "category": "productivity",
          "features": [
            "Every app in your Applications folders on macOS, every `.desktop` entry and flatpak on Linux",
            "Found by name or bundle id, so `Chrome` or `com.apple.` both work",
            "Running apps are tagged, with Quit (`cmd+q`) and Hide (`cmd+h`)",
            "System Settings panes as rows on macOS, found by words like `dark mode` or `dns`",
            "On Linux, an app's own actions (`New Private Window`) as secondary actions",
            "`cmd+i` shows where it lives, its version, bundle id and processes"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "The applications by name, the running ones tagged"
            },
            {
              "file": "2-search.png",
              "caption": "Typing at the root finds an app by its bundle id as well as its name: ical is Calendar (com.apple.iCal)"
            },
            {
              "file": "3-actions.png",
              "caption": "A running app: Open, Quit, Hide, Reveal in Finder, Copy path, Copy bundle id"
            },
            {
              "file": "4-panes.png",
              "caption": "The System Settings panes are rows too, found by what they hold: network finds Network and Wi-Fi"
            },
            {
              "file": "5-detail.png",
              "caption": "An app's details (cmd+i): its folder, running and its version, the bundle id and processes"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "keys": "enter"
            },
            {
              "title": "Quit",
              "description": "Asks the app through AppleScript, so it may ask you to save; a toast when it is not running.",
              "keys": "cmd+q"
            },
            {
              "title": "Hide",
              "description": "Through System Events.",
              "keys": "cmd+h"
            },
            {
              "title": "Reveal in Finder",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Copy path",
              "keys": "cmd+c"
            },
            {
              "title": "Copy bundle id",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy URL",
              "description": "On a System Settings pane: its x-apple.systempreferences: link.",
              "keys": "cmd+c"
            }
          ]
        },
        "palettes": {
          "apps": {
            "title": "Applications",
            "tier": "primary",
            "kind": "list",
            "description": "Everything that launches.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the app"
              },
              {
                "keys": "cmd+q",
                "title": "Quit a running app"
              },
              {
                "keys": "cmd+h",
                "title": "Hide a running app"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the path (a pane: its URL)"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the bundle id"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/apps",
      "tagline": "Every installed app, with its icon, a keystroke from launch",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/apps/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/4-panes-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/4-panes.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/apps/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/4-panes.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/apps/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/4-panes-dark.png",
        "https://pal.cagdas.io/extensions/apps/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "atc",
      "kind": "registry",
      "title": "atc",
      "description": "Your Claude Code sessions on every machine, through atc (github.com/zcag/atc): see which ones need you, answer them in a live chat or their own terminal, and start, resume or stop them without leaving pal.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M16.5 20.5a2.75 2.75 0 0 1 5.5 0v23a2.75 2.75 0 0 1-5.5 0zM29.5 23.25h15.25a2.75 2.75 0 0 1 0 5.5H29.5a2.75 2.75 0 0 1 0-5.5zM29.5 35.25h8.5a2.75 2.75 0 0 1 0 5.5h-8.5a2.75 2.75 0 0 1 0-5.5z",
          "box": 64,
          "bg": "#151c27"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/atc@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/atc",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "atc",
        "title": "atc",
        "description": "Your Claude Code sessions on every machine, through atc (github.com/zcag/atc): see which ones need you, answer them in a live chat or their own terminal, and start, resume or stop them without leaving pal.",
        "keywords": [
          "claude",
          "cc",
          "agents"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M16.5 20.5a2.75 2.75 0 0 1 5.5 0v23a2.75 2.75 0 0 1-5.5 0zM29.5 23.25h15.25a2.75 2.75 0 0 1 0 5.5H29.5a2.75 2.75 0 0 1 0-5.5zM29.5 35.25h8.5a2.75 2.75 0 0 1 0 5.5h-8.5a2.75 2.75 0 0 1 0-5.5z",
            "box": 64,
            "bg": "#151c27"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "url",
            "label": "atc server",
            "description": "The address of your atc server. Empty uses the one atc login saved on this machine.",
            "placeholder": "https://atc.example.internal",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "token",
            "label": "Token",
            "description": "What atc token prints on the server. Empty uses the one atc login saved; a server that trusts your tailnet needs none. Kept in the OS keychain.",
            "default": ""
          },
          {
            "kind": "select",
            "id": "open",
            "label": "Open a session in",
            "description": "Where Open in a terminal app goes. Auto runs atc attach in a terminal when the atc command is on this machine, and opens atc's web page otherwise.",
            "options": [
              {
                "id": "auto",
                "title": "Auto"
              },
              {
                "id": "terminal",
                "title": "A terminal (atc attach)"
              },
              {
                "id": "browser",
                "title": "atc's web page"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "select",
            "id": "terminal",
            "label": "Terminal",
            "description": "Which terminal atc attach opens in; Auto takes the first one installed.",
            "options": [
              {
                "id": "auto",
                "title": "Auto"
              },
              {
                "id": "kitty",
                "title": "kitty"
              },
              {
                "id": "Ghostty",
                "title": "Ghostty"
              },
              {
                "id": "iTerm2",
                "title": "iTerm2"
              },
              {
                "id": "Terminal",
                "title": "Terminal"
              },
              {
                "id": "Alacritty",
                "title": "Alacritty"
              }
            ],
            "default": "auto"
          }
        ],
        "palettes": {
          "sessions": {
            "title": "Sessions",
            "description": "Every session atc lists, the ones that need you first: the machine, folder and branch, what it is doing or asking to run, or what its turn ended on in one line; the pane leads with atc's summary of the reply, then your last message, the reply itself, its pages and what it spent.",
            "kind": "live",
            "lazy": true,
            "tier": "primary",
            "remember": false,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the chat (Tab, a message, Enter sends it first)"
              },
              {
                "keys": "cmd+y",
                "title": "Allow what it asks to run"
              },
              {
                "keys": "cmd+.",
                "title": "Say no, or interrupt a working turn"
              },
              {
                "keys": "cmd+o",
                "title": "Open its terminal in pal"
              },
              {
                "keys": "cmd+shift+t",
                "title": "Open in a terminal app (atc attach)"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in atc's web page"
              },
              {
                "keys": "cmd+u",
                "title": "Outputs: the servers, files and links it made"
              },
              {
                "keys": "cmd+l",
                "title": "Open its published page (several: its outputs)"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Resume a stopped session"
              },
              {
                "keys": "cmd+shift+p",
                "title": "Pin or unpin"
              },
              {
                "keys": "cmd+shift+e",
                "title": "Rename"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the resume command"
              },
              {
                "keys": "cmd+d",
                "title": "Stop the session (asks first)"
              }
            ]
          },
          "chat": {
            "title": "Chat",
            "description": "One session as a chat that follows it live: the conversation, a finished turn's long reply summed up under it, what it is doing now, a permission prompt with its two keys, its published pages, and a message field. Opened bare, the session that needs you most.",
            "kind": "view",
            "keys": [
              {
                "keys": "enter",
                "title": "Send the message (a stopped session is resumed first)"
              },
              {
                "keys": "cmd+y",
                "title": "Allow"
              },
              {
                "keys": "cmd+.",
                "title": "Say no, or interrupt"
              },
              {
                "keys": "cmd+shift+v",
                "title": "Attach the clipboard: text into the message, a picture or files uploaded with it"
              },
              {
                "keys": "cmd+o",
                "title": "Open its terminal in pal"
              },
              {
                "keys": "cmd+u",
                "title": "Outputs"
              },
              {
                "keys": "cmd+l",
                "title": "Open its published page"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the last reply"
              },
              {
                "keys": "cmd+[",
                "title": "Older messages"
              }
            ]
          },
          "terminal": {
            "title": "Terminal",
            "description": "A session's own terminal inside pal, Claude Code's screen as atc attach shows it, in the panel's colours: type into it, scroll it, answer any prompt. A stopped session is resumed first. Opened bare, the session that needs you most.",
            "kind": "view",
            "keys": [
              {
                "keys": "cmd+.",
                "title": "Send Escape (ctrl+[ too): interrupt, say no; Escape itself goes back"
              },
              {
                "keys": "cmd+shift+f",
                "title": "Fit the terminal to this window"
              }
            ]
          },
          "new": {
            "title": "New Session",
            "description": "Start Claude Code from one of atc's presets (a folder with standing instructions) or in a folder on any machine atc lists: the folders you used lately, then those under atc's roots; Tab to type the first message and a name.",
            "kind": "live",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Start a session there"
              },
              {
                "keys": "cmd+enter",
                "title": "Start it in a new git worktree"
              }
            ]
          },
          "history": {
            "title": "Earlier Conversations",
            "description": "Past conversations on every machine, newest first, found by title, folder or what you asked: read one, or resume it in the background.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Read it (a message typed after Tab resumes it)"
              },
              {
                "keys": "cmd+enter",
                "title": "Resume"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the resume command"
              }
            ]
          },
          "outputs": {
            "title": "Outputs",
            "description": "What your running sessions made: the pages they published first, with a preview, then the servers they started, the files they wrote or read, the links they gave.",
            "kind": "live",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the address or path"
              }
            ]
          }
        },
        "states": {
          "needs_you": {
            "description": "Sessions waiting on you to allow something or answer",
            "kind": "number"
          },
          "your_turn": {
            "description": "Sessions that finished their turn",
            "kind": "number"
          },
          "working": {
            "description": "Sessions working",
            "kind": "number"
          },
          "week_used": {
            "description": "How much of the plan's weekly limit is used, in percent",
            "kind": "number"
          }
        },
        "bar": {
          "sessions": {
            "title": "Sessions",
            "description": "A count per state in its colour (red needs you, amber your turn, blue working), the plan's limit once atc warns about it, an alarm while one needs you; the tooltip says what each finished turn ended on; the popover lists them by state on every machine with the plan's limits, opens a chat, allows or refuses a prompt, starts a new one.",
            "refresh": {
              "every": 30,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "needs": {
                "title": "One needs you",
                "item": {
                  "icon": {
                    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABHVBMVEUAAAD/ZmbvWFj/QED0WVnxVFvyVFvyVFvxVFvzUV3yU1nyVFvxU1vyVVz/SUnyU1ryVFv/VVXyVFzyU1vyVFvyVFvzVVvyVFuPmaOLlaeKlKaLlKeMlKeLlKiOjqqAgL+LlaeLlKeLlaeMlaeAgICLlKiLlaeKlKeLlaeImaqLlqeLlaeAmbOLlKeQkKaLlaeqqqqLlaeLlaeMlaeMlaiJlaiLlaeLlaeLlaeLlaeMlKWMk6aLlqaLlaeLlaaSkqSPlqWHlqWHl6eMmKqLlaeKlaf///+MlqaKlaqLlqiLlaeLlqiLlaiJl6WLlaeLlKeJlqqNlKiMlaeLlKfyVFzyVFvzVFvyV17zVVXyVFvzU1ryWVnvUlryVFuLlaew9jNLAAAAXXRSTlMABSAEF5fw75UWKOPiJwfZ1wZkYrCuzdIZY4GIfE8JBIv551QCrP5i9x7Qggq9F8oD9KuoWyn2zvXZHyin44QOIhEgKqlgAVAYYYByzzbG7ScmcTdh1eEmFe6TFB8mzDrZAAABXUlEQVRYw+3Y51ICMRAH8BNUUEHBQvHEE8WOep4FewNOsGAFG8n7P4YztnNGbrM7ySAf8n+A34dMdpNdw9Bpe7oCgaACprunl7FQuE/W6R9gH4lE5ZzBIfaVWFwKGmY/GZGCRj1oTApKeFBCCkp6UFJD/wWl0uOmIBOZSSFkTWU5ItMzAig3y3GZm4ehNMdmYRGEltAQX4agPN7hKxC0SoDWIMhex0MOeEYbeGgThLa2sU7Bhi9kZgfn7O6JSmT/AHFOh0fHiKLNpU4EOdWNTUMa6iTI/lu0Z3k6VCy17EiFskuDzn1bpGNRoCLQak0KVALaYraCh2ywY1fxEPxAXuAh+Mm+JJzRFQRdE6Ay4NRcAuQ6vs7NLelCWqbP1692R621SrXFZ/T+wdX9qAMgZYOfslH013D8KAXFY99OXW5cN6KRT6fxJLuKeA6HGHt5fVOwHQk2myqWLDptyTvp3wxbpPoI1AAAAABJRU5ErkJggg==",
                    "template": true
                  },
                  "segments": [
                    {
                      "id": "needs",
                      "text": "1",
                      "color": "red"
                    },
                    {
                      "id": "turn",
                      "text": "2",
                      "color": "amber"
                    },
                    {
                      "id": "working",
                      "text": "3",
                      "color": "blue"
                    }
                  ],
                  "tooltip": "1 needs you, 2 your turn, 3 working"
                }
              },
              "working": {
                "title": "All working",
                "item": {
                  "icon": {
                    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABHVBMVEUAAAD/ZmbvWFj/QED0WVnxVFvyVFvyVFvxVFvzUV3yU1nyVFvxU1vyVVz/SUnyU1ryVFv/VVXyVFzyU1vyVFvyVFvzVVvyVFuPmaOLlaeKlKaLlKeMlKeLlKiOjqqAgL+LlaeLlKeLlaeMlaeAgICLlKiLlaeKlKeLlaeImaqLlqeLlaeAmbOLlKeQkKaLlaeqqqqLlaeLlaeMlaeMlaiJlaiLlaeLlaeLlaeLlaeMlKWMk6aLlqaLlaeLlaaSkqSPlqWHlqWHl6eMmKqLlaeKlaf///+MlqaKlaqLlqiLlaeLlqiLlaiJl6WLlaeLlKeJlqqNlKiMlaeLlKfyVFzyVFvzVFvyV17zVVXyVFvzU1ryWVnvUlryVFuLlaew9jNLAAAAXXRSTlMABSAEF5fw75UWKOPiJwfZ1wZkYrCuzdIZY4GIfE8JBIv551QCrP5i9x7Qggq9F8oD9KuoWyn2zvXZHyin44QOIhEgKqlgAVAYYYByzzbG7ScmcTdh1eEmFe6TFB8mzDrZAAABXUlEQVRYw+3Y51ICMRAH8BNUUEHBQvHEE8WOep4FewNOsGAFG8n7P4YztnNGbrM7ySAf8n+A34dMdpNdw9Bpe7oCgaACprunl7FQuE/W6R9gH4lE5ZzBIfaVWFwKGmY/GZGCRj1oTApKeFBCCkp6UFJD/wWl0uOmIBOZSSFkTWU5ItMzAig3y3GZm4ehNMdmYRGEltAQX4agPN7hKxC0SoDWIMhex0MOeEYbeGgThLa2sU7Bhi9kZgfn7O6JSmT/AHFOh0fHiKLNpU4EOdWNTUMa6iTI/lu0Z3k6VCy17EiFskuDzn1bpGNRoCLQak0KVALaYraCh2ywY1fxEPxAXuAh+Mm+JJzRFQRdE6Ay4NRcAuQ6vs7NLelCWqbP1692R621SrXFZ/T+wdX9qAMgZYOfslH013D8KAXFY99OXW5cN6KRT6fxJLuKeA6HGHt5fVOwHQk2myqWLDptyTvp3wxbpPoI1AAAAABJRU5ErkJggg==",
                    "template": true
                  },
                  "segments": [
                    {
                      "id": "working",
                      "text": "2",
                      "color": "blue"
                    }
                  ],
                  "tooltip": "2 working"
                }
              },
              "quiet": {
                "title": "Nothing running",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": {
                      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABHVBMVEUAAAD/ZmbvWFj/QED0WVnxVFvyVFvyVFvxVFvzUV3yU1nyVFvxU1vyVVz/SUnyU1ryVFv/VVXyVFzyU1vyVFvyVFvzVVvyVFuPmaOLlaeKlKaLlKeMlKeLlKiOjqqAgL+LlaeLlKeLlaeMlaeAgICLlKiLlaeKlKeLlaeImaqLlqeLlaeAmbOLlKeQkKaLlaeqqqqLlaeLlaeMlaeMlaiJlaiLlaeLlaeLlaeLlaeMlKWMk6aLlqaLlaeLlaaSkqSPlqWHlqWHl6eMmKqLlaeKlaf///+MlqaKlaqLlqiLlaeLlqiLlaiJl6WLlaeLlKeJlqqNlKiMlaeLlKfyVFzyVFvzVFvyV17zVVXyVFvzU1ryWVnvUlryVFuLlaew9jNLAAAAXXRSTlMABSAEF5fw75UWKOPiJwfZ1wZkYrCuzdIZY4GIfE8JBIv551QCrP5i9x7Qggq9F8oD9KuoWyn2zvXZHyin44QOIhEgKqlgAVAYYYByzzbG7ScmcTdh1eEmFe6TFB8mzDrZAAABXUlEQVRYw+3Y51ICMRAH8BNUUEHBQvHEE8WOep4FewNOsGAFG8n7P4YztnNGbrM7ySAf8n+A34dMdpNdw9Bpe7oCgaACprunl7FQuE/W6R9gH4lE5ZzBIfaVWFwKGmY/GZGCRj1oTApKeFBCCkp6UFJD/wWl0uOmIBOZSSFkTWU5ItMzAig3y3GZm4ehNMdmYRGEltAQX4agPN7hKxC0SoDWIMhex0MOeEYbeGgThLa2sU7Bhi9kZgfn7O6JSmT/AHFOh0fHiKLNpU4EOdWNTUMa6iTI/lu0Z3k6VCy17EiFskuDzn1bpGNRoCLQak0KVALaYraCh2ywY1fxEPxAXuAh+Mm+JJzRFQRdE6Ay4NRcAuQ6vs7NLelCWqbP1692R621SrXFZ/T+wdX9qAMgZYOfslH013D8KAXFY99OXW5cN6KRT6fxJLuKeA6HGHt5fVOwHQk2myqWLDptyTvp3wxbpPoI1AAAAABJRU5ErkJggg==",
                      "template": true
                    },
                    "tooltip": "Nothing running"
                  }
                }
              }
            },
            "rules": [
              {
                "id": "needs",
                "when": "atc.needs_you \u003e 0",
                "description": "A session waits on you.",
                "urgent": true
              }
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the row's chat (r too)"
              },
              {
                "keys": "y",
                "title": "Allow what it asks to run"
              },
              {
                "keys": "i",
                "title": "Say no, or interrupt a working turn"
              },
              {
                "keys": "o",
                "title": "Open its terminal (in the popover)"
              },
              {
                "keys": "a",
                "title": "Open in a terminal app (atc attach)"
              },
              {
                "keys": "w",
                "title": "Open in atc's web page"
              },
              {
                "keys": "u",
                "title": "Outputs"
              },
              {
                "keys": "x",
                "title": "Stop the session (asks first)"
              },
              {
                "keys": "n",
                "title": "New session"
              },
              {
                "keys": "h",
                "title": "Earlier conversations"
              },
              {
                "keys": "p",
                "title": "Open Sessions in pal"
              },
              {
                "keys": "up",
                "title": "Move the cursor (down, j, k too; a click sets it)"
              }
            ]
          }
        },
        "links": {
          "open": {
            "description": "Open a session's chat",
            "params": {
              "session": {
                "description": "A session id, its background id, or words of its title; absent, the one that needs you most"
              }
            }
          },
          "send": {
            "description": "Send a message to a session",
            "params": {
              "session": {
                "description": "A session id, its background id, or words of its title",
                "required": true
              },
              "text": {
                "description": "The message"
              },
              "file": {
                "description": "A file to upload with it (repeat for several)",
                "type": "string[]"
              }
            }
          },
          "new": {
            "description": "Start a session, in a folder or from a preset",
            "params": {
              "dir": {
                "description": "The folder, absolute or under ~ (or a preset's)"
              },
              "preset": {
                "description": "A preset's name: its folder, name and standing instructions, on its own machine"
              },
              "prompt": {
                "description": "The first message"
              },
              "name": {
                "description": "A name for it"
              },
              "host": {
                "description": "The machine, when atc lists several"
              },
              "worktree": {
                "description": "In a new git worktree",
                "type": "boolean"
              }
            }
          }
        },
        "store": {
          "tagline": "Every Claude Code session on every machine, answered from pal",
          "category": "integration",
          "features": [
            "Every session on every machine your atc server lists, the ones that need you first, with what each is doing or asking to run",
            "A finished turn read in one line: atc's summary of the reply on the row, its gist and overview in the pane and the chat, the statuses in the bar's tooltip",
            "A chat per session that follows it live: read the conversation, type a message, `cmd+y` allows a prompt, `cmd+.` says no or interrupts",
            "A session's own terminal inside pal (`cmd+o`): Claude Code's screen live in the panel's colours, to type into, scroll and answer anything",
            "A bar item counting sessions by state, an alarm while one needs you, the plan's limit once it runs high; its popover answers them without opening pal",
            "Start Claude in a folder on any machine, in a new worktree, or from one of atc's presets, with the first message typed in the bar",
            "Earlier conversations from every machine, read or resumed in the background",
            "The pages a session published, the servers, files and links it made, one Enter from open; what each session spent; the clipboard attached with `cmd+shift+v`",
            "Built on atc (github.com/zcag/atc), a small server for Claude Code's background sessions; a machine where atc login was run needs no setup"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Every session on every machine atc lists: the ones that need you first, with what each is doing or asking to run"
            },
            {
              "file": "2-detail.png",
              "caption": "The pane: what a finished turn ended on, summed up by atc, then your message and the reply; its page and what it spent below"
            },
            {
              "file": "3-chat.png",
              "caption": "Enter opens the chat: the conversation live, the command it asks to run with cmd+y to allow and cmd+. to say no, a field to reply"
            },
            {
              "file": "4-new.png",
              "caption": "New Session: a folder on any machine, the first message typed after Tab"
            },
            {
              "file": "5-actions.png",
              "caption": "⌘K on a session: allow, say no, open it in a terminal or atc's page, its outputs, pin, park, rename, stop"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: how many sessions need you, are your turn and are working, the plan's limit once it runs high, an alarm while one needs you",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: every session by state on every machine, what each finished turn ended on, the plan's limits; Enter opens its chat, y allows, i says no",
              "kind": "bar",
              "box": [
                374,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-chat.png",
              "caption": "The chat in the popover: the conversation, its page, and what the turn ended on summed up, answered without opening pal",
              "kind": "bar",
              "box": [
                374,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the three counts in red, amber and blue",
              "kind": "bar"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/atc",
      "tagline": "Every Claude Code session on every machine, answered from pal",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/atc/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/3-chat-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/3-chat.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/4-new-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/4-new.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/5-actions-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/5-actions.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover-chat-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover-chat.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/atc/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/3-chat.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/4-new.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/5-actions.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover-chat.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/atc/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/3-chat-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/4-new-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/5-actions-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover-chat-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/atc/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "sessions",
          "title": "Sessions",
          "description": "A count per state in its colour (red needs you, amber your turn, blue working), the plan's limit once atc warns about it, an alarm while one needs you; the tooltip says what each finished turn ended on; the popover lists them by state on every machine with the plan's limits, opens a chat, allows or refuses a prompt, starts a new one.",
          "refresh": {
            "every": 30,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 30s, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "open",
          "url": "pal://atc/open",
          "cli": "pal call atc/open",
          "description": "Open a session's chat",
          "params": [
            {
              "name": "session",
              "description": "A session id, its background id, or words of its title; absent, the one that needs you most"
            }
          ]
        },
        {
          "route": "send",
          "url": "pal://atc/send?session=\u003csession\u003e",
          "cli": "pal call atc/send session=\u003csession\u003e",
          "description": "Send a message to a session",
          "params": [
            {
              "name": "session",
              "description": "A session id, its background id, or words of its title",
              "required": true
            },
            {
              "name": "text",
              "description": "The message"
            },
            {
              "name": "file",
              "description": "A file to upload with it (repeat for several)",
              "type": "string[]"
            }
          ]
        },
        {
          "route": "new",
          "url": "pal://atc/new",
          "cli": "pal call atc/new",
          "description": "Start a session, in a folder or from a preset",
          "params": [
            {
              "name": "dir",
              "description": "The folder, absolute or under ~ (or a preset's)"
            },
            {
              "name": "preset",
              "description": "A preset's name: its folder, name and standing instructions, on its own machine"
            },
            {
              "name": "prompt",
              "description": "The first message"
            },
            {
              "name": "name",
              "description": "A name for it"
            },
            {
              "name": "host",
              "description": "The machine, when atc lists several"
            },
            {
              "name": "worktree",
              "description": "In a new git worktree",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "audio",
      "kind": "bundled",
      "title": "Audio",
      "description": "Switch the sound output or input, set the volume and mute, from a list of every audio device.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰕾",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/audio@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/audio",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "audio",
        "title": "Audio",
        "description": "Switch the sound output or input, set the volume and mute, from a list of every audio device.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰕾",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "Switch the output or input, set the volume, mute",
          "category": "system",
          "features": [
            "Every output and input in two sections, the default tagged, the volume and mute state on the right",
            "`enter` makes a device the default for output or input",
            "`cmd+shift+v` sets the volume to the percent you type",
            "`cmd+m` toggles mute",
            "The connection (Bluetooth, USB, built-in, HDMI) in the subtitle when the system reports it"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-devices.png",
              "caption": "Outputs and inputs in two sections, the defaults tagged, a muted device marked, the volume on the right"
            },
            {
              "file": "2-actions.png",
              "caption": "What a device can do: make it the output, set its volume, mute it"
            },
            {
              "file": "3-volume.png",
              "caption": "Set volume with nothing typed in the bar asks for the percent here, 0 to 100"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the speaker glyph, and the new level beside it for a moment after a change",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-call.png",
              "caption": "The rest of the time one glyph that says where the sound goes: headphones while the AirPods play",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the output in use on a card with a slider and mute, the other outputs as rows, the input in one line",
              "kind": "bar",
              "box": [
                452,
                64,
                840,
                872
              ]
            },
            {
              "file": "bar-popover-call.png",
              "caption": "On a call through the AirPods with the microphone muted: the input line says so in red",
              "kind": "bar",
              "box": [
                452,
                64,
                840,
                872
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the speaker glyph with the level as the label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Set as output / Set as input",
              "description": "Makes the row the default for its direction; the HUD names it.",
              "keys": "enter"
            },
            {
              "title": "Set volume",
              "description": "The percent typed in the bar, 0 to 100, on a device with a volume control.",
              "keys": "cmd+shift+v"
            },
            {
              "title": "Mute / Unmute",
              "description": "Toggles mute and stays in the list.",
              "keys": "cmd+m"
            }
          ]
        },
        "palettes": {
          "audio": {
            "title": "Audio",
            "kind": "live",
            "description": "Every output and input, the defaults tagged, with their volume.",
            "keys": [
              {
                "keys": "enter",
                "title": "Set as the default output or input"
              },
              {
                "keys": "cmd+shift+v",
                "title": "Set the volume to the percent typed in the bar"
              },
              {
                "keys": "cmd+m",
                "title": "Mute or unmute"
              }
            ]
          }
        },
        "states": {
          "input": {
            "description": "The default input: live, muted, or none",
            "kind": "string"
          }
        },
        "bar": {
          "volume": {
            "title": "Volume",
            "description": "The default output's route, and its level for a moment after you change it (see Volume level in the bar). Click mutes, scroll adjusts by 5%. The popover leads with the device in use — a slider a click sets anywhere along it, the level and a mute switch — then the other outputs as rows a click makes default, and the input in one line under them.",
            "keys": [
              {
                "keys": "enter",
                "title": "Use the focused device as the output"
              },
              {
                "keys": "m",
                "title": "Mute or unmute the output in use"
              },
              {
                "keys": "-, +",
                "title": "Quieter or louder by 5%"
              },
              {
                "keys": "0 … 4",
                "title": "Set 0, 25, 50, 75 or 100%; a click anywhere on the slider sets that point"
              },
              {
                "keys": "p",
                "title": "Open the Audio palette in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the other outputs; a click on one focuses it"
              }
            ],
            "refresh": {
              "every": 5,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "speakers": {
                "title": "Built-in speakers",
                "item": {
                  "icon": "󰖀",
                  "icon_size": 18,
                  "icon_width": 31,
                  "tooltip": "MacBook Pro Speakers · 38%"
                }
              },
              "flash": {
                "title": "Just after a change",
                "item": {
                  "icon": "󰕾",
                  "title": "72%",
                  "icon_size": 18,
                  "icon_width": 31,
                  "tooltip": "MacBook Pro Speakers · 72%"
                }
              },
              "quiet": {
                "title": "Turned right down",
                "item": {
                  "icon": "󰕿",
                  "icon_size": 18,
                  "icon_width": 31,
                  "tooltip": "MacBook Pro Speakers · 12%"
                }
              },
              "headphones": {
                "title": "Bluetooth headphones",
                "item": {
                  "icon": "󰋋",
                  "icon_size": 18,
                  "icon_width": 31,
                  "tooltip": "Px8 · 62%"
                }
              },
              "muted": {
                "title": "Muted",
                "item": {
                  "icon": "󰝟",
                  "color": "muted",
                  "icon_size": 18,
                  "icon_width": 31,
                  "tooltip": "MacBook Pro Speakers, muted"
                }
              },
              "missing": {
                "title": "No output device",
                "item": {
                  "hidden": true,
                  "icon_size": 18,
                  "icon_width": 31,
                  "empty": {
                    "icon": "󰝟",
                    "tooltip": "No output device"
                  }
                }
              }
            },
            "settings": [
              {
                "kind": "select",
                "id": "level",
                "label": "Volume level in the bar",
                "description": "The percentage changes only when you change it, so as a permanent fixture it is a number you stop reading. After a change it appears for three seconds as feedback and then collapses back to the glyph alone; the standing answer is the popover, where it sits against the device it applies to. Always keeps it on screen, Never leaves the glyph to speak.",
                "options": [
                  {
                    "id": "flash",
                    "title": "For a moment after a change"
                  },
                  {
                    "id": "always",
                    "title": "Always"
                  },
                  {
                    "id": "never",
                    "title": "Never"
                  }
                ],
                "default": "flash"
              }
            ]
          },
          "microphone": {
            "title": "Microphone",
            "description": "Visible only when the default input is muted or absent. Click restores it to 75%. The popover leads with the microphone in use — a slider, its level and a mute switch — then the other inputs as rows a click makes default, and the output in one line under them.",
            "keys": [
              {
                "keys": "enter",
                "title": "Use the focused device as the input"
              },
              {
                "keys": "m",
                "title": "Mute or unmute the microphone"
              },
              {
                "keys": "-, +",
                "title": "Quieter or louder by 5%"
              },
              {
                "keys": "0 … 4",
                "title": "Set 0, 25, 50, 75 or 100%; a click anywhere on the slider sets that point"
              },
              {
                "keys": "p",
                "title": "Open the Audio palette in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the other inputs; a click on one focuses it"
              }
            ],
            "refresh": {
              "every": 5,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "muted": {
                "title": "Muted microphone",
                "item": {
                  "icon": "󰍭",
                  "color": "red",
                  "tooltip": "MacBook Pro Microphone, muted"
                }
              },
              "missing": {
                "title": "No input device",
                "item": {
                  "icon": "󰍮",
                  "color": "red",
                  "tooltip": "No input device"
                }
              },
              "normal": {
                "title": "Input available",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰍬",
                    "tooltip": "MacBook Pro Microphone · 75%"
                  }
                }
              }
            },
            "rules": [
              {
                "id": "live",
                "when": "audio.input == 'live'",
                "description": "A live mic needs no attention: off the strip.",
                "hidden": true
              },
              {
                "id": "muted",
                "when": "audio.input == 'muted'",
                "description": "Muted: red, so a call finds it.",
                "color": "red"
              },
              {
                "id": "missing",
                "when": "audio.input == 'none'",
                "description": "No input device: red (turn Hidden on to leave it quiet).",
                "color": "red"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/audio",
      "tagline": "Switch the output or input, set the volume, mute",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/audio/screenshots/1-devices-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/1-devices.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/3-volume-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/3-volume.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar-call-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar-call.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover-call-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover-call.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/audio/screenshots/1-devices.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/3-volume.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar-call.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover-call.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/audio/screenshots/1-devices-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/3-volume-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar-call-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover-call-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/audio/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "volume",
          "title": "Volume",
          "description": "The default output's route, and its level for a moment after you change it (see Volume level in the bar). Click mutes, scroll adjusts by 5%. The popover leads with the device in use — a slider a click sets anywhere along it, the level and a mute switch — then the other outputs as rows a click makes default, and the input in one line under them.",
          "refresh": {
            "every": 5,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 5s, on wake"
        },
        {
          "id": "microphone",
          "title": "Microphone",
          "description": "Visible only when the default input is muted or absent. Click restores it to 75%. The popover leads with the microphone in use — a slider, its level and a mute switch — then the other inputs as rows a click makes default, and the output in one line under them.",
          "refresh": {
            "every": 5,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 5s, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "blackjack",
      "kind": "registry",
      "title": "Blackjack",
      "description": "Blackjack on a felt table with a real shoe, played one-handed with the arrows or with the mouse. Your bankroll and record are kept across restarts.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󱢡",
          "bg": "red"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/blackjack@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/blackjack",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "blackjack",
        "title": "Blackjack",
        "description": "Blackjack on a felt table with a real shoe, played one-handed with the arrows or with the mouse. Your bankroll and record are kept across restarts.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󱢡",
            "bg": "red"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "number",
            "id": "decks",
            "label": "Decks",
            "description": "Decks in the shoe; it is reshuffled once a quarter is left.",
            "min": 1,
            "max": 8,
            "default": 6
          },
          {
            "kind": "number",
            "id": "starting_bankroll",
            "label": "Starting bankroll",
            "description": "Chips a new game starts with.",
            "min": 10,
            "max": 1000000,
            "step": 10,
            "unit": "$",
            "default": 1000
          },
          {
            "kind": "number",
            "id": "min_bet",
            "label": "Minimum bet",
            "description": "The smallest bet, and the step + and - move it by.",
            "min": 1,
            "max": 10000,
            "unit": "$",
            "default": 10
          },
          {
            "kind": "boolean",
            "id": "dealer_hits_soft_17",
            "label": "Dealer hits soft 17",
            "text": "H17: the dealer draws on a soft 17",
            "description": "Off, the dealer stands on every 17 (S17). Applies from the next hand.",
            "default": false
          },
          {
            "kind": "boolean",
            "id": "insurance",
            "label": "Offer insurance",
            "text": "Ask when the dealer shows an ace",
            "description": "Up or I takes it for half the bet; down or Enter declines. Off, the hand plays on without the question.",
            "default": false
          }
        ],
        "sync": {
          "state": "local",
          "winnings": "sum",
          "stats": {
            "fields": {
              "hands": "sum",
              "wins": "sum",
              "losses": "sum",
              "pushes": "sum",
              "blackjacks": "sum",
              "net": "sum"
            }
          },
          "peak": "max",
          "longest": "max"
        },
        "leaderboards": [
          {
            "id": "bankroll",
            "title": "Biggest bankroll",
            "order": "desc",
            "format": "points",
            "min": 1000,
            "max": 1000000000
          },
          {
            "id": "streak",
            "title": "Longest winning streak",
            "order": "desc",
            "format": "points",
            "min": 1,
            "max": 1000
          }
        ],
        "store": {
          "tagline": "Blackjack on felt, arrows or mouse; the bankroll persists",
          "category": "fun",
          "features": [
            "A casino table in the panel: cards dealt in dealer order, the hole card flipping, chips for the bet",
            "One-handed: arrows set the bet, `enter` deals, then `up` hit, `down` stand, `right` double, `left` split",
            "Every move is a button with its key on it; the title says what happens next",
            "Standard rules: dealer stands on 17, blackjack pays 3:2, double after split; H17 and insurance as settings",
            "Leave with `escape` any time; the hand, the bankroll and the record are there when you come back",
            "Signed in to pal, your chips and record follow you to every machine; the biggest bankroll and the longest winning streak go on leaderboards"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-blackjack.png",
              "caption": "A blackjack: 3:2 on the $50 bet, the winnings stacked beside it",
              "cover": [
                378,
                270,
                684,
                335
              ]
            },
            {
              "file": "2-hand.png",
              "caption": "Mid-hand after a split: hand 1 is being played, the hole card is face down"
            },
            {
              "file": "3-settled.png",
              "caption": "Settled: the dealer drew and bust, the winnings stacked on the bet, the bankroll moved"
            },
            {
              "file": "4-bet.png",
              "caption": "Placing a bet: the chips on the felt, up and down move it by the minimum, Enter deals"
            }
          ],
          "actions": [
            {
              "title": "Deal",
              "description": "Also Next hand once a hand is settled.",
              "keys": "enter"
            },
            {
              "title": "Hit",
              "keys": "up, h"
            },
            {
              "title": "Stand",
              "description": "Enter stands too.",
              "keys": "down, s"
            },
            {
              "title": "Double down",
              "description": "On the first two cards: one card, then stand.",
              "keys": "right, d"
            },
            {
              "title": "Split",
              "description": "A pair, once; split aces take one card each.",
              "keys": "left, p"
            },
            {
              "title": "Raise the bet",
              "keys": "up, +"
            },
            {
              "title": "Lower the bet",
              "keys": "down, -"
            },
            {
              "title": "Take insurance",
              "description": "Offered on an ace with `insurance` on; down or Enter declines.",
              "keys": "up, i"
            },
            {
              "title": "New game",
              "description": "A fresh bankroll and record; asks first.",
              "keys": "n"
            }
          ],
          "play": true
        },
        "palettes": {
          "blackjack": {
            "title": "Blackjack",
            "kind": "view",
            "description": "The table. Escape leaves mid-hand; the hand is there when you come back.",
            "keys": [
              {
                "keys": "enter",
                "title": "Deal, stand, or the next hand; declines insurance"
              },
              {
                "keys": "up",
                "title": "Hit; raise the bet; take insurance"
              },
              {
                "keys": "down",
                "title": "Stand; lower the bet; no insurance"
              },
              {
                "keys": "right",
                "title": "Double down"
              },
              {
                "keys": "left",
                "title": "Split"
              },
              {
                "keys": "h",
                "title": "Hit"
              },
              {
                "keys": "s",
                "title": "Stand"
              },
              {
                "keys": "d",
                "title": "Double down"
              },
              {
                "keys": "p",
                "title": "Split"
              },
              {
                "keys": "+",
                "title": "Raise the bet"
              },
              {
                "keys": "-",
                "title": "Lower the bet"
              },
              {
                "keys": "i",
                "title": "Take insurance, when offered"
              },
              {
                "keys": "n",
                "title": "New game, after a confirm"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/blackjack",
      "tagline": "Blackjack on felt, arrows or mouse; the bankroll persists",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/blackjack/screenshots/1-blackjack-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/1-blackjack.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/2-hand-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/2-hand.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/3-settled-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/3-settled.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/4-bet-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/4-bet.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/blackjack/screenshots/1-blackjack.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/2-hand.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/3-settled.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/4-bet.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/blackjack/screenshots/1-blackjack-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/2-hand-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/3-settled-dark.png",
        "https://pal.cagdas.io/extensions/blackjack/screenshots/4-bet-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "bluetooth",
      "kind": "bundled",
      "title": "Bluetooth",
      "description": "Connect and disconnect your paired Bluetooth devices, with their battery levels in view.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰂯",
          "bg": "blue"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/bluetooth@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/bluetooth",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "bluetooth",
        "title": "Bluetooth",
        "description": "Connect and disconnect your paired Bluetooth devices, with their battery levels in view.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰂯",
            "bg": "blue"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "Connect and disconnect paired devices, battery in view",
          "category": "system",
          "features": [
            "Every paired device, connected ones first, with a mark for its kind (headphones, keyboard, mouse, controller)",
            "Battery levels when the device reports them; AirPods show left, right and case",
            "`enter` connects or disconnects; disconnecting asks first",
            "`cmd+c` copies the device address",
            "Nothing to install on macOS; uses `bluetoothctl` on Linux"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-devices.png",
              "caption": "Paired devices, the connected ones first with their battery, the AirPods bud by bud"
            },
            {
              "file": "2-actions.png",
              "caption": "A device that is away: connect it, or copy its address"
            },
            {
              "file": "3-disconnect.png",
              "caption": "Enter on a connected device disconnects it, after asking"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar only while a device runs low: the count, red once one is at 20% or under",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-one.png",
              "caption": "One device low: its name and level, amber until it reaches 20%",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the lowest battery leads, large, then the other low ones and the rest; Enter disconnects, c copies the address",
              "kind": "bar",
              "box": [
                414,
                64,
                840,
                890
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the battery alert and the low count on red",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Connect / Disconnect",
              "description": "Toggles the connection; Disconnect asks first; the HUD says which happened. Mark several devices to connect or disconnect them together.",
              "keys": "enter"
            },
            {
              "title": "Copy address",
              "keys": "cmd+c"
            }
          ]
        },
        "palettes": {
          "bluetooth": {
            "title": "Bluetooth",
            "kind": "live",
            "description": "Every paired device, the connected ones first, with battery when the OS reports it.",
            "keys": [
              {
                "keys": "enter",
                "title": "Connect or disconnect"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the address"
              }
            ]
          }
        },
        "states": {
          "low": {
            "description": "Connected devices at or under the low threshold",
            "kind": "number"
          },
          "lowest": {
            "description": "The lowest battery among the connected devices, percent",
            "kind": "number"
          },
          "connected": {
            "description": "Connected devices",
            "kind": "number"
          }
        },
        "bar": {
          "battery": {
            "keys": [
              {
                "keys": "enter",
                "title": "Disconnect the focused device"
              },
              {
                "keys": "c",
                "title": "Copy the focused device address"
              },
              {
                "keys": "s",
                "title": "Open Bluetooth Settings"
              },
              {
                "keys": "r",
                "title": "Refresh the battery readings"
              }
            ],
            "title": "Bluetooth Battery",
            "description": "Visible only when a connected device with a reported battery reaches the low alert level. Click opens Bluetooth Settings; the popover leads with the lowest battery, large, then the other low devices, the other connected battery readings and connected devices with no reading.",
            "refresh": {
              "every": 60,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "low": {
                "title": "Low headphones",
                "item": {
                  "icon": "󰂃",
                  "title": "AirPods Pro 24%",
                  "color": "amber",
                  "tooltip": "AirPods Pro 24% (L 28% · R 24% · Case 62%)"
                }
              },
              "critical": {
                "title": "Critical devices",
                "item": {
                  "icon": "󰂃",
                  "title": "2 low",
                  "color": "red",
                  "tooltip": "Corne 8% · AirPods Pro 14%"
                }
              },
              "connected": {
                "title": "All healthy, the connected devices kept on the bar (Connected)",
                "item": {
                  "icon": "󰂱",
                  "color": "muted",
                  "tooltip": "AirPods Pro 84% · Corne 91%"
                }
              },
              "clear": {
                "title": "All healthy",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰂯",
                    "tooltip": "No connected devices"
                  }
                }
              }
            },
            "rules": [
              {
                "id": "none",
                "when": "bluetooth.connected == 0",
                "description": "Nothing connected: off the strip.",
                "hidden": true
              },
              {
                "id": "fine",
                "when": "bluetooth.low == 0",
                "description": "Nothing low: off the strip (turn Hidden off to keep a muted glyph up while a device is connected).",
                "hidden": true,
                "color": "muted"
              },
              {
                "id": "low",
                "when": "bluetooth.low \u003e 0",
                "description": "A device is low: a reminder.",
                "color": "amber"
              },
              {
                "id": "critical",
                "when": "bluetooth.low \u003e 0 and bluetooth.lowest \u003c= 20",
                "description": "Act now.",
                "color": "red"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "low_threshold",
                "label": "Low battery alert",
                "description": "A connected device at or below this level counts as low: named on the bar item, and its rules show the item. At 20% or below (or this level when lower) the tint is red.",
                "min": 1,
                "max": 100,
                "unit": "%",
                "default": 25
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/bluetooth",
      "tagline": "Connect and disconnect paired devices, battery in view",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/1-devices-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/1-devices.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/3-disconnect-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/3-disconnect.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar-one-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar-one.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/1-devices.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/3-disconnect.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar-one.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/1-devices-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/3-disconnect-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar-one-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/bluetooth/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "battery",
          "title": "Bluetooth Battery",
          "description": "Visible only when a connected device with a reported battery reaches the low alert level. Click opens Bluetooth Settings; the popover leads with the lowest battery, large, then the other low devices, the other connected battery readings and connected devices with no reading.",
          "refresh": {
            "every": 60,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 1 min, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "bookmarks",
      "kind": "bundled",
      "title": "Bookmarks",
      "description": "Search the bookmarks of every browser you use, plus links of your own, and open one in the browser it came from. A second list searches your browsing history.",
      "version": "0.2.0",
      "icon": {
        "tile": {
          "glyph": "󰃀",
          "bg": "orange"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/bookmarks@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/bookmarks",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "bookmarks",
        "title": "Bookmarks",
        "description": "Search the bookmarks of every browser you use, plus links of your own, and open one in the browser it came from. A second list searches your browsing history.",
        "version": "0.2.0",
        "icon": {
          "tile": {
            "glyph": "󰃀",
            "bg": "orange"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "file",
            "label": "Bookmarks file",
            "pick": "file",
            "description": "A JSON array of {name, url, subtitle?, icon?, keywords?}; the url is opened or copied. Optional: without the file the browsers alone are listed.",
            "default": "~/.config/pal/data/bookmarks.json"
          },
          {
            "kind": "list",
            "id": "browsers",
            "label": "Browsers",
            "description": "Whose bookmarks to list, in order (the first wins a url two have): chrome, brave, edge, chromium, vivaldi, arc, safari, firefox. Empty lists the file alone.",
            "placeholder": "chrome",
            "default": [
              "chrome",
              "brave",
              "edge",
              "chromium",
              "vivaldi",
              "arc",
              "safari",
              "firefox"
            ]
          },
          {
            "kind": "list",
            "id": "exclude_folders",
            "label": "Exclude folders",
            "description": "Bookmark folders skipped, by name (`Archive`) or a short path (`Bookmarks Bar/Old`).",
            "placeholder": "Archive",
            "default": []
          }
        ],
        "store": {
          "tagline": "Bookmarks from every browser and your own links, in one search",
          "category": "productivity",
          "features": [
            "Chrome, Brave, Edge, Chromium, Vivaldi, Arc, Safari and Firefox, every profile",
            "Your own links from a JSON file, with names, keywords and icons",
            "Found by name, address or folder; a link saved twice is listed once",
            "Open it, open it in the browser it came from, or copy it plain or as a markdown link",
            "Browser History: search pages you visited in Chrome-family browsers and Firefox, newest first"
          ],
          "permissions": [
            "full-disk-access"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "The file's links first, then each browser in its section, the folder on the right"
            },
            {
              "file": "2-search.png",
              "caption": "A folder name is a keyword: typing it finds what is filed under it"
            },
            {
              "file": "3-actions.png",
              "caption": "Open in browser, Copy link, Copy as markdown, Open in Chrome"
            },
            {
              "file": "4-history.png",
              "caption": "Browser History: what the browsers visited, searched by title and address, newest first with when; Enter opens it in the browser it came from"
            }
          ],
          "actions": [
            {
              "title": "Open in browser",
              "description": "The system's default browser. Every action here works on several marked rows: they open together, copies go one per line.",
              "keys": "enter"
            },
            {
              "title": "Copy link",
              "keys": "cmd+c"
            },
            {
              "title": "Copy as markdown",
              "description": "[name](url).",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Open in Chrome, Safari, Firefox",
              "description": "On a browser's row: the browser it came from."
            },
            {
              "title": "Open in Chrome, Firefox (history)",
              "description": "On a Browser History row: the page in the browser it came from.",
              "keys": "enter"
            },
            {
              "title": "Open in default browser (history)",
              "keys": "cmd+o"
            }
          ]
        },
        "palettes": {
          "bookmarks": {
            "title": "Bookmarks",
            "tier": "primary",
            "kind": "list",
            "description": "The links in the file and the browsers, by name, folder and keyword.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy as markdown"
              }
            ]
          },
          "history": {
            "title": "Browser History",
            "kind": "input",
            "description": "What the browsers visited (Chrome, Brave, Edge, Chromium, Vivaldi, Arc, Firefox; every profile), searched by title and address on every keystroke, newest first; the last visit on the right. Each browser's history file is copied under pal's cache before it is read, since a running browser holds it locked; the copy follows the file, at most every 30 s. Safari's history needs Full Disk Access and is not read.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in the browser it came from"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+o",
                "title": "Open in the default browser"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/bookmarks",
      "tagline": "Bookmarks from every browser and your own links, in one search",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/4-history-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/4-history.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/4-history.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/bookmarks/screenshots/4-history-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "browser-tabs",
      "kind": "bundled",
      "title": "Browser Tabs",
      "description": "Every tab open in your browsers, with its favicon: `enter` switches to it, and you can close, mute or copy it from the list.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰓩",
          "bg": "cyan"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/browser-tabs@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/browser-tabs",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "browser-tabs",
        "title": "Browser Tabs",
        "description": "Every tab open in your browsers, with its favicon: `enter` switches to it, and you can close, mute or copy it from the list.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰓩",
            "bg": "cyan"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "suggests": [
          "appletv"
        ],
        "settings": [
          {
            "kind": "number",
            "id": "port",
            "label": "DevTools port",
            "description": "The --remote-debugging-port of a Chromium browser (Chrome, Brave, Edge, Chromium). When something listens there its tabs come over the DevTools protocol, with playing and muted state; otherwise the browsers below are asked.",
            "min": 1,
            "max": 65535,
            "default": 9222
          },
          {
            "kind": "list",
            "id": "apps",
            "label": "Scriptable browsers",
            "description": "macOS only: browsers asked over AppleScript when they are running, by app name. A Chromium browser already on the DevTools port is skipped.",
            "placeholder": "Safari",
            "default": [
              "Safari",
              "Google Chrome"
            ]
          },
          {
            "kind": "boolean",
            "id": "firefox",
            "label": "Firefox",
            "text": "List Firefox tabs from its session file",
            "description": "Read-only: Firefox has no scripting interface, so Focus only raises its window.",
            "default": true
          },
          {
            "kind": "path",
            "id": "firefox_session",
            "label": "Firefox session file",
            "description": "A sessionstore-backups/recovery.jsonlz4; empty finds the most recent profile's.",
            "pick": "file",
            "default": ""
          }
        ],
        "store": {
          "tagline": "Switch to any open tab of Chrome, Safari or Firefox",
          "category": "productivity",
          "features": [
            "Tabs from Chrome, Safari and Firefox, and any Chromium browser with remote debugging on",
            "Tab titles show up in the main search, so typing a page's name finds it",
            "While a browser is in front, its tabs come first in the main search",
            "Filters for All, Playing sound and This window",
            "Close (`cmd+w`), mute (`cmd+m`), copy the address (`cmd+c`) or a markdown link (`cmd+shift+c`)",
            "With Apple TV installed, a YouTube video plays on the TV (`cmd+t`), from where the tab is once it has started",
            "Firefox tabs can be listed and focused, but not closed or muted"
          ],
          "permissions": [
            "automation",
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "The tabs of two browsers in their own order, the host as the subtitle, where each is and playing or muted on the right"
            },
            {
              "file": "2-audible.png",
              "caption": "The Audible filter: only the tabs a page reports as playing sound, across windows"
            },
            {
              "file": "3-actions.png",
              "caption": "Focus, Copy URL, Mute, Copy as markdown link, and Close last"
            },
            {
              "file": "4-root.png",
              "caption": "Live: tab titles are root results, so part of one typed at the root finds the tab"
            },
            {
              "file": "5-detail.png",
              "caption": "A tab's details (cmd+i): its browser and window, playing, the address"
            }
          ],
          "actions": [
            {
              "title": "Focus",
              "description": "Selects the tab in the browser, then raises its window; for Firefox only the window.",
              "keys": "enter"
            },
            {
              "title": "Play on Apple TV",
              "description": "A YouTube video, with Apple TV installed: from where the tab is once it has started (from the start on cmd+shift+t). The tab pauses as the TV takes over.",
              "keys": "cmd+t"
            },
            {
              "title": "Copy URL",
              "keys": "cmd+c"
            },
            {
              "title": "Mute / Unmute",
              "description": "DevTools tabs only: the page's media elements, not Chrome's tab mute.",
              "keys": "cmd+m"
            },
            {
              "title": "Copy as markdown link",
              "description": "[title](url).",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Close",
              "description": "Not for Firefox.",
              "keys": "cmd+w"
            }
          ]
        },
        "palettes": {
          "tabs": {
            "title": "Browser Tabs",
            "tier": "primary",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "front": [
              "com.google.Chrome",
              "com.google.Chrome.canary",
              "org.chromium.Chromium",
              "com.brave.Browser",
              "com.microsoft.edgemac",
              "com.vivaldi.Vivaldi",
              "company.thebrowser.Browser",
              "com.apple.Safari",
              "org.mozilla.firefox"
            ],
            "description": "Open tabs across Chrome, Safari and Firefox.",
            "keys": [
              {
                "keys": "enter",
                "title": "Switch to the tab"
              },
              {
                "keys": "cmd+t",
                "title": "Play a YouTube video on the Apple TV, from where it is"
              },
              {
                "keys": "cmd+w",
                "title": "Close the tab"
              },
              {
                "keys": "cmd+m",
                "title": "Mute or unmute the tab"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the URL"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy as a markdown link"
              },
              {
                "keys": "tab",
                "title": "All, Audible, This window"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/browser-tabs",
      "tagline": "Switch to any open tab of Chrome, Safari or Firefox",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/2-audible-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/2-audible.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/4-root-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/4-root.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/2-audible.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/4-root.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/2-audible-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/4-root-dark.png",
        "https://pal.cagdas.io/extensions/browser-tabs/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "calc",
      "kind": "bundled",
      "title": "Calculator",
      "description": "Answers what you type as you type it: arithmetic, units, currencies, percentages, dates, time zones and durations, with variables of your own.",
      "version": "0.2.0",
      "icon": {
        "tile": {
          "glyph": "󰃬",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/calc@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/calc",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "calc",
        "title": "Calculator",
        "description": "Answers what you type as you type it: arithmetic, units, currencies, percentages, dates, time zones and durations, with variables of your own.",
        "version": "0.2.0",
        "icon": {
          "tile": {
            "glyph": "󰃬",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "number",
            "id": "precision",
            "label": "Precision",
            "description": "Significant digits in a result; integers are never rounded, units and rates show at most 6.",
            "min": 2,
            "max": 20,
            "default": 10
          },
          {
            "kind": "text",
            "id": "locale",
            "label": "Locale",
            "description": "How numbers and dates are written (en: 1,234.5; tr: 1.234,5; de: 1.234,5). Also how a typed number is read.",
            "default": "en"
          },
          {
            "kind": "text",
            "id": "home_currency",
            "label": "Home currency",
            "description": "What a bare amount (12 usd) converts to. Empty: the time zone's currency.",
            "placeholder": "TRY",
            "default": ""
          },
          {
            "kind": "list",
            "id": "vars",
            "label": "Variables",
            "description": "One line per variable, `name = value`, a value being anything calc reads: `salary_hour = 54 usd`, `rent = 42000 try`, `height = 183 cm`. A value may use other variables (`salary_day = salary_hour * 8`) and is written with a dot for decimals whatever the locale. A name is letters, digits and underscores, not a currency. Then `rent / salary_month`, `salary_year to eur`, `height to ft`; the row's subtitle says what each name stood for.",
            "placeholder": "rent = 42000 try",
            "default": []
          }
        ],
        "store": {
          "tagline": "Sums, units, currencies, dates and time zones as you type",
          "category": "productivity",
          "features": [
            "Arithmetic, percentages and number bases: `2^10`, `15% of 240`, `255 to hex`",
            "Units as people type them: `5 km to miles`, `72 f to c`, `50 lbs` straight to kg",
            "30 currencies by code, symbol or name (`€12 to $`), rates updated daily",
            "Dates and time zones: `next friday`, `days until 25 dec`, `3pm istanbul to new york`",
            "Your own variables: `rent = 42000 try`, then `rent / 12`",
            "A second answer in the other form: the reverse conversion, a fraction, hex, the ISO date"
          ],
          "permissions": [
            "network",
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-currency.png",
              "caption": "12 usd to try at the ECB's rate, the reverse as the second row; the pane shows the rate, its inverse and where it comes from"
            },
            {
              "file": "2-dates.png",
              "caption": "A day count, with the weeks and months on the right"
            },
            {
              "file": "3-timezone.png",
              "caption": "10:00 UTC in Tokyo, the full date there as the second row"
            },
            {
              "file": "4-actions.png",
              "caption": "What a result can do: copy, paste into the app in front, copy without formatting"
            }
          ],
          "actions": [
            {
              "title": "Copy result",
              "description": "The result as shown.",
              "keys": "enter"
            },
            {
              "title": "Paste result",
              "description": "Into the app that was in front.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy without formatting",
              "description": "No grouping or symbols: 583.68, 1000000.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy expression = result",
              "keys": "cmd+shift+e"
            }
          ]
        },
        "palettes": {
          "calc": {
            "title": "Calculator",
            "kind": "input",
            "inline": true,
            "match": "\\d[-+*/^%=()a-z\\s]|[-+*/^%=()a-z]\\s*\\d|\\b(now|today|tomorrow|yesterday|next|last|unix|epoch)\\b|^time in |\\s+time$|\\bweek\\b|^@?1\\d{9}$",
            "fallback": true,
            "description": "Type an expression; the result is the row. At the root, sums, conversions, dates, times in other zones and unix times answer inline under a Calculator section; a query that is none of those gets an Ask Calculator fallback row.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the result"
              },
              {
                "keys": "cmd+enter",
                "title": "Paste the result"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy without formatting"
              },
              {
                "keys": "cmd+shift+e",
                "title": "Copy expression = result"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/calc",
      "tagline": "Sums, units, currencies, dates and time zones as you type",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/calc/screenshots/1-currency-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/1-currency.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/2-dates-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/2-dates.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/3-timezone-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/3-timezone.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/4-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/calc/screenshots/1-currency.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/2-dates.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/3-timezone.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/4-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/calc/screenshots/1-currency-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/2-dates-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/3-timezone-dark.png",
        "https://pal.cagdas.io/extensions/calc/screenshots/4-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "calendar",
      "kind": "registry",
      "title": "Calendar",
      "description": "Your upcoming events with the current one marked, and a meeting about to start at the top of the panel, one key to join the call. Add events with a form or one typed line like `standup tomorrow 10:00`.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰃭",
          "bg": "red"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/calendar@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/calendar",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "calendar",
        "title": "Calendar",
        "description": "Your upcoming events with the current one marked, and a meeting about to start at the top of the panel, one key to join the call. Add events with a form or one typed line like `standup tomorrow 10:00`.",
        "keywords": [
          "cal"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰃭",
            "bg": "red"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "source",
            "label": "Source",
            "description": "Where the events come from. Auto is Google once an account is listed below, else the system calendar (EventKit on macOS, khal on Linux).",
            "options": [
              {
                "id": "auto",
                "title": "Auto"
              },
              {
                "id": "system",
                "title": "System calendar"
              },
              {
                "id": "google",
                "title": "Google Calendar"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "list",
            "id": "accounts",
            "label": "Google accounts",
            "placeholder": "work = gcloud auth application-default print-access-token",
            "description": "One per line as `name = command`: the command prints an access token for the Calendar API (a bare token, or the JSON of an OAuth endpoint with access_token and expires_in). The command owns the secret; pal keeps the token in memory until it expires. In the config file an entry may be a table { name, token_command, calendars } to read calendars other than the primary.",
            "default": []
          },
          {
            "kind": "list",
            "id": "calendars",
            "label": "Calendars",
            "placeholder": "Work",
            "description": "Calendar names (or ids) to show; empty shows every calendar. The filter dropdown narrows further.",
            "default": []
          },
          {
            "kind": "number",
            "id": "days",
            "label": "Days ahead",
            "description": "How many days from today My Schedule lists.",
            "min": 1,
            "max": 90,
            "step": 1,
            "unit": "days",
            "default": 7
          },
          {
            "kind": "boolean",
            "id": "hide_declined",
            "label": "Hide declined",
            "text": "Leave out invitations you declined",
            "default": true
          },
          {
            "kind": "number",
            "id": "horizon_hours",
            "label": "Bar horizon",
            "description": "The bar item shows the next event only when it starts within this many hours; nothing sooner, no item.",
            "min": 1,
            "max": 48,
            "step": 1,
            "unit": "hours",
            "default": 10
          },
          {
            "kind": "boolean",
            "id": "hide_all_day",
            "label": "Skip all-day events on the bar",
            "text": "The bar item speaks for timed events only",
            "default": true
          },
          {
            "kind": "number",
            "id": "call_lead",
            "label": "Call row from",
            "description": "An event with a call gets a Join row at the top of pal this many minutes before it starts, until ten minutes in.",
            "min": 1,
            "max": 30,
            "step": 1,
            "unit": "min",
            "default": 5
          },
          {
            "kind": "number",
            "id": "default_length",
            "label": "Quick Add length",
            "description": "How long an event typed without an end or a `for` lasts.",
            "min": 5,
            "max": 480,
            "step": 5,
            "unit": "min",
            "default": 30
          }
        ],
        "store": {
          "tagline": "Today at a glance, one key to join the call",
          "category": "productivity",
          "features": [
            "Today and My Schedule: events in order, each tagged `in 12 min`, `now` or `over`",
            "`enter` joins the Zoom, Meet, Teams or Webex call, or opens the event",
            "A call about to start sits at the top of the panel before you type anything",
            "The next event on the menu bar, amber inside 15 minutes and red inside 5; a click joins",
            "Add events by form or one line (`dentist fri 2pm-3pm`); delete one after a confirmation",
            "Reads Calendar.app's accounts on macOS, `khal` on Linux, or Google Calendar directly"
          ],
          "permissions": [
            "calendars"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-schedule.png",
              "caption": "What is left of today and the days after, the next event tagged with how soon, calls tagged Join"
            },
            {
              "file": "2-detail.png",
              "caption": "The detail pane: when and the calendar over the title, your reply, the notes, then the call, the organizer and the attendees with their replies"
            },
            {
              "file": "3-new.png",
              "caption": "New event: a title, a day in words, the times from the next quarter hour, the calendar"
            },
            {
              "file": "4-today.png",
              "caption": "Today: the whole day in order, what is over greyed, the rest with how long until it starts"
            },
            {
              "file": "5-quick.png",
              "caption": "Quick Add: a line typed, the event read back with its day, time, place and calendar before Enter adds it"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the next event and how long until it, the glyph amber inside fifteen minutes, a dot for a call to join",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-urgent.png",
              "caption": "Inside five minutes the glyph turns red",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the day: what is still to come with the time, the place and the people, Join on the calls, tomorrow folded under its header",
              "kind": "bar",
              "box": [
                326,
                64,
                840,
                806
              ]
            },
            {
              "file": "bar-popover-now.png",
              "caption": "While a call runs its row sits on a card with what is left of it, the strip green; Enter joins",
              "kind": "bar",
              "box": [
                252,
                64,
                840,
                806
              ]
            },
            {
              "file": "bar-popover-tomorrow.png",
              "caption": "Late in the day: what is left, and t opens tomorrow in the same shape; the arrows walk the rows",
              "kind": "bar",
              "box": [
                358,
                64,
                840,
                886
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the same item, amber with the call's dot",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Join call",
              "description": "Opens the meeting link; first when the event has one.",
              "keys": "enter"
            },
            {
              "title": "Open in Calendar",
              "description": "Shows the event in Calendar.app (macOS), or opens it in Google Calendar for a Google account.",
              "keys": "enter"
            },
            {
              "title": "Copy conference link",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy event details",
              "description": "Title, when, where and the link as text.",
              "keys": "cmd+c"
            },
            {
              "title": "Delete event",
              "description": "Asks first; on a repeating event only this occurrence goes (macOS).",
              "keys": "ctrl+x"
            },
            {
              "title": "New event",
              "description": "The form, then the event in the chosen calendar.",
              "keys": "enter"
            },
            {
              "title": "Add event",
              "description": "Quick Add: the line as typed becomes the event.",
              "keys": "enter"
            },
            {
              "title": "Grant access",
              "description": "On the permission row: the system prompt, or System Settings when it was denied.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "schedule": {
            "title": "My Schedule",
            "kind": "live",
            "remember": false,
            "ttl": 60,
            "description": "The next days' events in time order, sectioned by day, the current or next one tagged; a New event row at the end (system calendar).",
            "keys": [
              {
                "keys": "enter",
                "title": "Join the call, else open in Calendar"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the conference link"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the event details"
              },
              {
                "keys": "ctrl+x",
                "title": "Delete the event"
              }
            ]
          },
          "today": {
            "title": "Today",
            "kind": "live",
            "remember": false,
            "ttl": 60,
            "description": "The day's events in order with the time, how long, and where each stands (`in 12 min`, `now, 25 min left`, `over`); tomorrow's once today is done; what the bar item opens. At the root, a Join row for a call from a few minutes before it starts until ten minutes in.",
            "keys": [
              {
                "keys": "enter",
                "title": "Join the call, else open in Calendar"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the conference link"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the event details"
              },
              {
                "keys": "cmd+i",
                "title": "Details: the description, the attendees with their replies, the link"
              }
            ]
          },
          "quick": {
            "title": "Quick Add Event",
            "kind": "input",
            "fallback": "Add “{query}” to the calendar",
            "description": "One line into an event: a title, then a day (`tomorrow`, `fri`, `next tue`, `20 sep`, `2026-09-20`), a time or a range (`10:00`, `2pm-3pm`, `14:00 to 15:30`), `for 45m`, `at \u003cplace\u003e`, `@ \u003ccalendar\u003e` (or `in \u003ccalendar\u003e` when one starts with the word), `all day`. No time: all day; no day: today, or tomorrow once the time has passed. The row shows the event read back as you type; Enter adds it. At the root a query nothing matched gets an Add fallback row.",
            "keys": [
              {
                "keys": "enter",
                "title": "Add the event as read"
              }
            ]
          }
        },
        "states": {
          "phase": {
            "description": "The next event's time state: far, near, warning, critical, running, or none within the horizon",
            "kind": "string"
          },
          "minutes": {
            "description": "Minutes until the next event starts (negative while it runs)",
            "kind": "number"
          },
          "call": {
            "description": "The next event has a call to join",
            "kind": "boolean"
          }
        },
        "bar": {
          "upcoming": {
            "title": "Upcoming",
            "description": "The next event's name with `in 12m` beside it, `25m left` while it runs (and `in 8m` for the one due next); hidden when nothing starts within the horizon; a dot when there is a call to join. The colour follows the rules: muted far off and near, amber from Warning from, red from Critical from, green while it runs. A click joins the call, or opens Calendar; a hover peek opens the day with Join on the calls, the running event on a card, tomorrow folded.",
            "mocks": {
              "far": {
                "title": "Starts in 3 hours",
                "item": {
                  "icon": "󰃭",
                  "title": "Project review",
                  "segments": [
                    {
                      "id": "when",
                      "text": "in 3h"
                    }
                  ],
                  "color": "muted",
                  "badge": "dot"
                }
              },
              "near": {
                "title": "Starts in 45 minutes",
                "item": {
                  "icon": "󰃭",
                  "title": "Project review",
                  "segments": [
                    {
                      "id": "when",
                      "text": "in 45m"
                    }
                  ],
                  "color": "muted",
                  "badge": "dot"
                }
              },
              "warning": {
                "title": "Starts in 12 minutes",
                "item": {
                  "icon": "󰃭",
                  "title": "Project review",
                  "segments": [
                    {
                      "id": "when",
                      "text": "in 12m"
                    }
                  ],
                  "color": "amber",
                  "badge": "dot"
                }
              },
              "critical": {
                "title": "Starts in 4 minutes",
                "item": {
                  "icon": "󰃭",
                  "title": "Project review",
                  "segments": [
                    {
                      "id": "when",
                      "text": "in 4m"
                    }
                  ],
                  "color": "red",
                  "badge": "dot"
                }
              },
              "running": {
                "title": "In progress, 25 minutes left",
                "item": {
                  "icon": "󰃭",
                  "title": "Project review",
                  "segments": [
                    {
                      "id": "when",
                      "text": "25m left"
                    }
                  ],
                  "color": "green",
                  "badge": "dot"
                }
              },
              "running-next": {
                "title": "In progress, the next one in 8 minutes",
                "item": {
                  "icon": "󰃭",
                  "title": "Project review",
                  "segments": [
                    {
                      "id": "when",
                      "text": "12m left"
                    },
                    {
                      "id": "next",
                      "text": "in 8m",
                      "color": "amber",
                      "tooltip": "Design sync, 11:00 – 11:30 (Team)"
                    }
                  ],
                  "color": "green",
                  "badge": "dot",
                  "tooltip": "Project review, 10:20 – 10:50 (Work), Enter joins; then Design sync, 11:00 – 11:30 (Team)"
                }
              }
            },
            "refresh": {
              "every": 300,
              "on": [
                "minute",
                "wake",
                "network"
              ]
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Join the focused event's call, else open it in Calendar (Google Calendar for a Google account)"
              },
              {
                "keys": "j",
                "title": "Join the next call"
              },
              {
                "keys": "t",
                "title": "Show or fold tomorrow"
              },
              {
                "keys": "o",
                "title": "Open Calendar (the day's page on calendar.google.com for a Google account)"
              },
              {
                "keys": "r",
                "title": "Refresh"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the focused event's details"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the focused event's conference link"
              },
              {
                "keys": "up, down",
                "title": "Move between the rows; a click on a row focuses it, a click on Join joins it"
              }
            ],
            "rules": [
              {
                "id": "far",
                "when": "calendar.phase == 'far'",
                "description": "Beyond Near from: nothing pressing.",
                "color": "muted"
              },
              {
                "id": "near",
                "when": "calendar.phase == 'near'",
                "description": "Inside Near from, before Warning from.",
                "color": "muted"
              },
              {
                "id": "warning",
                "when": "calendar.phase == 'warning'",
                "description": "Inside Warning from.",
                "color": "amber"
              },
              {
                "id": "critical",
                "when": "calendar.phase == 'critical'",
                "description": "Inside Critical from: about to start.",
                "color": "red"
              },
              {
                "id": "running",
                "when": "calendar.phase == 'running'",
                "description": "Under way: what is left of it.",
                "color": "green"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "near_minutes",
                "label": "Near from",
                "description": "Inside this many minutes, Upcoming uses its near appearance. Warning and critical cutoffs below still take precedence.",
                "min": 1,
                "max": 720,
                "step": 1,
                "unit": "min",
                "default": 60
              },
              {
                "kind": "number",
                "id": "warn_minutes",
                "label": "Warning from",
                "description": "The bar item uses its warning appearance this many minutes before the event.",
                "min": 1,
                "max": 120,
                "step": 1,
                "unit": "min",
                "default": 15
              },
              {
                "kind": "number",
                "id": "urgent_minutes",
                "label": "Critical from",
                "description": "The bar item uses its critical appearance this many minutes before the event.",
                "min": 0,
                "max": 60,
                "step": 1,
                "unit": "min",
                "default": 5
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/calendar",
      "tagline": "Today at a glance, one key to join the call",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/calendar/screenshots/1-schedule-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/1-schedule.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/3-new-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/3-new.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/4-today-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/4-today.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/5-quick-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/5-quick.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar-urgent-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar-urgent.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-now-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-now.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-tomorrow-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-tomorrow.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/calendar/screenshots/1-schedule.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/3-new.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/4-today.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/5-quick.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar-urgent.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-now.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-tomorrow.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/calendar/screenshots/1-schedule-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/3-new-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/4-today-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/5-quick-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar-urgent-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-now-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-tomorrow-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/calendar/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "upcoming",
          "title": "Upcoming",
          "description": "The next event's name with `in 12m` beside it, `25m left` while it runs (and `in 8m` for the one due next); hidden when nothing starts within the horizon; a dot when there is a call to join. The colour follows the rules: muted far off and near, amber from Warning from, red from Critical from, green while it runs. A click joins the call, or opens Calendar; a hover peek opens the day with Join on the calls, the running event on a card, tomorrow folded.",
          "refresh": {
            "every": 300,
            "on": [
              "minute",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, every minute, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "clipboard",
      "kind": "bundled",
      "title": "Clipboard",
      "description": "Everything you copied, text, images and files, searchable and a keystroke from being pasted back into the app in front. Pin what you reuse; edit, name or save an entry, or copy the text out of an image.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰅍",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/clipboard@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/clipboard",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "clipboard",
        "title": "Clipboard",
        "description": "Everything you copied, text, images and files, searchable and a keystroke from being pasted back into the app in front. Pin what you reuse; edit, name or save an entry, or copy the text out of an image.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰅍",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "ocr_concealed",
            "label": "OCR copies are private",
            "text": "Text read from an image (Copy text from image) is kept out of this history",
            "default": false
          },
          {
            "kind": "select",
            "id": "primary_action",
            "label": "Primary action",
            "description": "What Enter does on an entry.",
            "options": [
              {
                "id": "paste",
                "title": "Paste into the app in front"
              },
              {
                "id": "copy",
                "title": "Copy to the clipboard"
              }
            ],
            "default": "paste"
          }
        ],
        "store": {
          "tagline": "Everything you copied, with images; Enter pastes it back",
          "category": "productivity",
          "features": [
            "Text, images and files you copied, searched as you type, with a preview beside the list",
            "Pinned entries stay at the top and never expire",
            "Filters for text, images, files, links and colours (drawn as swatches)",
            "`enter` pastes into the app in front, `cmd+shift+v` as plain text, `cmd+shift+t` copies the text in an image",
            "Edit, name, save as a file or snippet, or show as a QR code",
            "Password manager copies and excluded apps are never recorded"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "The history with the pane open: pinned first (a named entry by its name), then newest, the source app and the time on the right"
            },
            {
              "file": "2-image.png",
              "caption": "An image entry: the picture in the pane, under its pixels and size"
            },
            {
              "file": "3-colors.png",
              "caption": "The Colors filter: a copied colour is its own swatch on the row and in the pane"
            },
            {
              "file": "4-actions.png",
              "caption": "Paste, Copy, Open link, Edit, Pin, Name, Save as file, Save as snippet, Show as QR code, Delete, Clear history"
            },
            {
              "file": "5-edit.png",
              "caption": "Edit (cmd+E): the text in a textarea; the submit copies it, so the edited text is the newest entry"
            },
            {
              "file": "6-qr.png",
              "caption": "Show as QR code (cmd+shift+K): the entry's text as a code to scan, large in a level"
            }
          ],
          "actions": [
            {
              "title": "Paste",
              "description": "Hides the panel and pastes the entry into the app that was in front.",
              "keys": "enter"
            },
            {
              "title": "Copy",
              "description": "Puts the entry back on the clipboard.",
              "keys": "cmd+enter"
            },
            {
              "title": "Open link",
              "description": "On an entry that is one url.",
              "keys": "cmd+o"
            },
            {
              "title": "Paste as plain text",
              "keys": "cmd+shift+v"
            },
            {
              "title": "Copy image file",
              "description": "The PNG the recorder keeps, as a file.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy text from image",
              "description": "OCR over the image (Vision on macOS, tesseract on Linux); the text goes on the clipboard.",
              "keys": "cmd+shift+t"
            },
            {
              "title": "Edit…",
              "description": "On a text entry: a textarea with the text; the submit copies the edited text (a box pastes it too), so it is the newest entry.",
              "keys": "cmd+e"
            },
            {
              "title": "Pin / Unpin",
              "description": "Pinned entries sort first and never expire.",
              "keys": "cmd+p"
            },
            {
              "title": "Name / Rename",
              "description": "The name typed in the bar titles the row and is searched like the text; blank clears it.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Save as file…",
              "description": "A folder (the Desktop) and a name from the entry: the text, the image's PNG, or the file list as paths. An existing name is refused.",
              "keys": "cmd+s"
            },
            {
              "title": "Save as snippet",
              "description": "On a text entry: the Snippets form, pre-filled.",
              "keys": "cmd+shift+s"
            },
            {
              "title": "Show as QR code",
              "description": "On a text entry up to 2000 characters: the code large in a level.",
              "keys": "cmd+shift+k"
            },
            {
              "title": "Delete",
              "description": "Asks first.",
              "keys": "cmd+d"
            },
            {
              "title": "Delete all unpinned",
              "description": "Asks first; pinned entries stay."
            },
            {
              "title": "Clear history",
              "description": "Asks first; pinned entries included.",
              "keys": "cmd+shift+d"
            }
          ]
        },
        "links": {
          "copy": {
            "description": "Put a history entry back on the clipboard",
            "params": {
              "index": {
                "description": "Which entry, newest first: 0 is the newest (the default)",
                "type": "number"
              }
            }
          }
        },
        "palettes": {
          "rows": {
            "title": "Clipboard",
            "kind": "input",
            "description": "What is on the clipboard now, as the things it could be: a web address (open, private window, markdown link, QR code), a colour (the picker, every notation), paths (open, reveal, open with), an email, a phone number, JSON (pretty, minified), an expression or a number (the answer, other bases), a timestamp or ISO date (local and relative), hex or base64 that decodes to text, a tracking number (the carrier), a git sha or owner/repo#12 (GitHub), an image (save, copy as file, OCR), and the text itself (counts, case and slug transforms, paste as plain, save as snippet). The root's Clipboard section before you type; Hide keeps it away until the next copy. Only what history recorded is read: a concealed copy or one from an excluded app never shows.",
            "settings": [
              {
                "kind": "boolean",
                "id": "fetch_titles",
                "label": "Fetch page titles",
                "text": "Ask a copied web address for its title (one request, 1 s at most; the only thing these rows send off the machine)",
                "default": true
              },
              {
                "kind": "text",
                "id": "shortener",
                "label": "URL shortener",
                "description": "A URL with {url} in it whose response body is the short link, for the Shorten action (https://is.gd/create.php?format=simple\u0026url={url}). Empty: no Shorten action.",
                "placeholder": "https://is.gd/create.php?format=simple\u0026url={url}",
                "default": ""
              },
              {
                "kind": "text",
                "id": "private_browser",
                "label": "Private window browser",
                "description": "Which browser opens a private window: Google Chrome, Brave Browser, Microsoft Edge, Chromium, Vivaldi or Firefox. Empty: the first of those that is installed.",
                "placeholder": "Firefox",
                "default": ""
              }
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "What the row is for: open, call, paste as plain, copy the answer"
              },
              {
                "keys": "cmd+shift+h",
                "title": "Hide the section until the next copy"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the address in a private window"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Copy as a Markdown link, or minified JSON"
              },
              {
                "keys": "cmd+s",
                "title": "Save the text as a snippet"
              }
            ]
          },
          "history": {
            "title": "Clipboard History",
            "on": [
              "clipboard"
            ],
            "kind": "input",
            "description": "Every copy, pinned ones first, then newest.",
            "keys": [
              {
                "keys": "enter",
                "title": "Paste into the app in front"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy back to the clipboard"
              },
              {
                "keys": "cmd+o",
                "title": "Open the link"
              },
              {
                "keys": "cmd+shift+v",
                "title": "Paste as plain text"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy an image as a file"
              },
              {
                "keys": "cmd+shift+t",
                "title": "Copy the text in an image (OCR)"
              },
              {
                "keys": "cmd+e",
                "title": "Edit a text entry; the edited text is copied"
              },
              {
                "keys": "cmd+p",
                "title": "Pin or unpin"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Name or rename the entry to what is typed in the bar"
              },
              {
                "keys": "cmd+s",
                "title": "Save as a file"
              },
              {
                "keys": "cmd+shift+s",
                "title": "Save a text entry as a snippet"
              },
              {
                "keys": "cmd+shift+k",
                "title": "Show a text entry as a QR code"
              },
              {
                "keys": "cmd+d",
                "title": "Delete the entry"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Clear history"
              },
              {
                "keys": "tab",
                "title": "Text, Images, Files, Links, Colors"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/clipboard",
      "tagline": "Everything you copied, with images; Enter pastes it back",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/clipboard/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/2-image-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/2-image.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/3-colors-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/3-colors.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/5-edit-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/5-edit.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/6-qr-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/6-qr.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/clipboard/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/2-image.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/3-colors.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/5-edit.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/6-qr.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/clipboard/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/2-image-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/3-colors-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/5-edit-dark.png",
        "https://pal.cagdas.io/extensions/clipboard/screenshots/6-qr-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "copy",
          "url": "pal://clipboard/copy",
          "cli": "pal call clipboard/copy",
          "description": "Put a history entry back on the clipboard",
          "params": [
            {
              "name": "index",
              "description": "Which entry, newest first: 0 is the newest (the default)",
              "type": "number"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "clock",
      "kind": "bundled",
      "title": "Clock",
      "description": "The date and time on the bar, and a popover with the time to the second, the month with the week numbers, and world clocks for the cities you work with. A day opens in Calendar.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰅐",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/clock@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/clock",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "clock",
        "title": "Clock",
        "description": "The date and time on the bar, and a popover with the time to the second, the month with the week numbers, and world clocks for the cities you work with. A day opens in Calendar.",
        "keywords": [
          "time",
          "date",
          "world clock",
          "timezone"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰅐",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "suggests": [
          "calendar"
        ],
        "settings": [
          {
            "kind": "list",
            "id": "zones",
            "label": "World clocks",
            "placeholder": "Tokyo",
            "description": "One per line: a city (Tokyo, New York), a zone (Europe/Berlin), or a label of your own (Office = Europe/London). `z` in the popover adds one.",
            "default": []
          },
          {
            "kind": "boolean",
            "id": "hour12",
            "label": "12-hour clock",
            "text": "2:05 PM rather than 14:05",
            "default": false
          },
          {
            "kind": "select",
            "id": "week_start",
            "label": "Week starts on",
            "options": [
              {
                "id": "monday",
                "title": "Monday"
              },
              {
                "id": "sunday",
                "title": "Sunday"
              }
            ],
            "default": "monday"
          }
        ],
        "store": {
          "tagline": "The time on the bar, the month and world clocks a click away",
          "category": "productivity",
          "features": [
            "The date and time on the menu bar or sketchybar, on the minute, with seconds if you like",
            "A click opens the time to the second, the date, the week number and the day of the year",
            "The month with today filled; arrows walk the days, `[` and `]` the months, `t` comes back",
            "World clocks: the time in each city, how far ahead or behind, a moon at night and `tomorrow` when the date has turned",
            "`z` adds a city by name (Tokyo, New York) or zone; Enter opens the day in Calendar"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-clock.png",
              "caption": "Clock in the panel, from root search: the time and the world clocks beside the month"
            },
            {
              "file": "2-later.png",
              "caption": "A 12-hour clock and weeks from Sunday, two settings; the ring walked into October, the header saying how far"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the day and the time, turning on the minute",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-seconds.png",
              "caption": "The weekday alone and the seconds, two settings of the item",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the time to the second with the date and the week, the month with today filled, and the world clocks with a moon where it is night",
              "kind": "bar",
              "box": [
                360,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-day.png",
              "caption": "The arrows walk the days and the month's header says how far; Enter opens the day in Calendar",
              "kind": "bar",
              "box": [
                360,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-field.png",
              "caption": "z adds a world clock: a city, a zone, or a name of your own",
              "kind": "bar",
              "box": [
                360,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the same label, in place of the stock clock",
              "kind": "bar"
            }
          ]
        },
        "palettes": {
          "clock": {
            "title": "Clock",
            "kind": "view",
            "description": "The time, the month and your world clocks; a day opens in Calendar.",
            "keywords": [
              "calendar month",
              "week number",
              "what day"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the ringed day in Calendar"
              },
              {
                "keys": "left",
                "title": "Walk the days (up and down by weeks)"
              },
              {
                "keys": "[",
                "title": "The month before (`]` after)"
              },
              {
                "keys": "t",
                "title": "Back to today"
              },
              {
                "keys": "c",
                "title": "Copy the ringed day's date"
              },
              {
                "keys": "z",
                "title": "Add a world clock"
              }
            ]
          }
        },
        "bar": {
          "time": {
            "title": "Date and Time",
            "description": "`Thu 8 Oct 14:32`, turning on the minute (or the second). A click opens the time to the second with the date and week, the month to walk with the arrows, and your world clocks; Enter opens the ringed day in Calendar.",
            "refresh": {
              "every": 300,
              "on": [
                "wake"
              ]
            },
            "settings": [
              {
                "kind": "select",
                "id": "date",
                "label": "Date",
                "options": [
                  {
                    "id": "day",
                    "title": "Thu 8 Oct"
                  },
                  {
                    "id": "weekday",
                    "title": "Thu"
                  },
                  {
                    "id": "none",
                    "title": "None"
                  }
                ],
                "default": "day"
              },
              {
                "kind": "boolean",
                "id": "seconds",
                "label": "Seconds",
                "text": "Show the seconds on the bar",
                "default": false
              }
            ],
            "mocks": {
              "day": {
                "title": "Date and time",
                "item": {
                  "title": "Thu 8 Oct 14:32",
                  "tooltip": "Thursday 8 October 2026, week 41"
                }
              },
              "weekday": {
                "title": "Weekday only",
                "item": {
                  "title": "Thu 14:32",
                  "tooltip": "Thursday 8 October 2026, week 41"
                }
              },
              "seconds": {
                "title": "With seconds",
                "item": {
                  "title": "Thu 8 Oct 14:32:07",
                  "tooltip": "Thursday 8 October 2026, week 41"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the ringed day in Calendar"
              },
              {
                "keys": "left",
                "title": "Walk the days (up and down by weeks)"
              },
              {
                "keys": "[",
                "title": "The month before (`]` after)"
              },
              {
                "keys": "t",
                "title": "Back to today"
              },
              {
                "keys": "c",
                "title": "Copy the ringed day's date"
              },
              {
                "keys": "z",
                "title": "Add a world clock"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/clock",
      "tagline": "The time on the bar, the month and world clocks a click away",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/clock/screenshots/1-clock-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/1-clock.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/2-later-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/2-later.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar-seconds-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar-seconds.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-day-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-day.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-field-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-field.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/clock/screenshots/1-clock.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/2-later.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar-seconds.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-day.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-field.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/clock/screenshots/1-clock-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/2-later-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar-seconds-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-day-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-field-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/clock/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "time",
          "title": "Date and Time",
          "description": "`Thu 8 Oct 14:32`, turning on the minute (or the second). A click opens the time to the second with the date and week, the month to walk with the arrows, and your world clocks; Enter opens the ringed day in Calendar.",
          "refresh": {
            "every": 300,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 5 min, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "colors",
      "kind": "bundled",
      "title": "Colors",
      "description": "A colour picker for the keyboard: pick a pixel off the screen, type any notation, or walk hue and lightness with the arrows, then copy the colour in any notation. Also named palettes as swatch grids, a history and a converter.",
      "version": "0.2.0",
      "icon": {
        "tile": {
          "glyph": "󰏘",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/colors@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/colors",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "colors",
        "title": "Colors",
        "description": "A colour picker for the keyboard: pick a pixel off the screen, type any notation, or walk hue and lightness with the arrows, then copy the colour in any notation. Also named palettes as swatch grids, a history and a converter.",
        "version": "0.2.0",
        "icon": {
          "tile": {
            "glyph": "󰏘",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "format",
            "label": "Copy as",
            "description": "The notation `c` and Copy write; every other notation stays a keystroke away in the picker and the action panel.",
            "options": [
              {
                "id": "hex",
                "title": "Hex (#ff8800)"
              },
              {
                "id": "rgb",
                "title": "rgb(255, 136, 0)"
              },
              {
                "id": "hsl",
                "title": "hsl(32, 100%, 50%)"
              },
              {
                "id": "hwb",
                "title": "hwb(32 0% 0%)"
              },
              {
                "id": "oklch",
                "title": "oklch(0.744 0.181 56.5)"
              },
              {
                "id": "oklab",
                "title": "oklab(0.744 0.078 0.163)"
              },
              {
                "id": "lab",
                "title": "lab(67.75 42.16 74.06)"
              },
              {
                "id": "p3",
                "title": "color(display-p3 0.939 0.558 0.222)"
              },
              {
                "id": "name",
                "title": "The CSS name (nearest when inexact)"
              }
            ],
            "default": "hex"
          },
          {
            "kind": "boolean",
            "id": "uppercase",
            "label": "Uppercase hex",
            "text": "#FF8800 rather than #ff8800",
            "default": false
          },
          {
            "kind": "select",
            "id": "alpha",
            "label": "Alpha",
            "description": "What a translucent colour writes: the alpha kept (`#ff880080`, `rgba(…)`, `/ 0.5`) or dropped, so every copy is opaque.",
            "options": [
              {
                "id": "keep",
                "title": "Keep the alpha"
              },
              {
                "id": "drop",
                "title": "Drop it, copy the opaque colour"
              }
            ],
            "default": "keep"
          },
          {
            "kind": "list",
            "id": "sets",
            "label": "Sets shown",
            "description": "Which named sets the grid lists under All: css, tailwind, material3, material, apple, catppuccin, rosepine, nord, solarized, pal. The filter dropdown still reaches every set.",
            "placeholder": "tailwind",
            "default": [
              "css",
              "tailwind",
              "material3",
              "material",
              "apple",
              "catppuccin",
              "rosepine",
              "nord",
              "solarized",
              "pal"
            ]
          },
          {
            "kind": "number",
            "id": "history_size",
            "label": "History size",
            "description": "How many picked and copied colours the history keeps, newest first, one entry per colour.",
            "min": 5,
            "max": 500,
            "default": 50
          }
        ],
        "store": {
          "tagline": "Pick, type or walk a colour, then copy it in any notation",
          "category": "developer",
          "features": [
            "Pick a pixel off the screen with the system's loupe; the Pick Colour row copies it straight away",
            "Every notation at once (hex, rgb, hsl, oklch, lab, display-p3, CSS name), plus contrast with AA/AAA badges",
            "Arrows walk hue and lightness, `-` and `+` saturation; `m` switches between HSL and OKLCH",
            "Tints, shades and harmonies as tiles to pick from",
            "Named palettes as swatch grids: CSS, Tailwind, Material, Apple, Catppuccin, Rosé Pine, Nord, Solarized",
            "A history of every colour you picked or copied, and a converter for any notation"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-picker.png",
              "caption": "The picker: the swatch over the hue strip and the plane, every notation, the nearest tokens, contrast, tints, shades and harmonies"
            },
            {
              "file": "2-shades.png",
              "caption": "Tab onto the shades: the arrows walk the row, the label names the tile, Enter takes it"
            },
            {
              "file": "3-typing.png",
              "caption": "Typing a notation: a digit or # opens the field in the search row, Enter applies it"
            },
            {
              "file": "4-sets.png",
              "caption": "The named sets as swatch grids, one section per set, a filter per set"
            },
            {
              "file": "5-history.png",
              "caption": "The history: every picked and copied colour with when and where from, and the screen pick at the top"
            },
            {
              "file": "6-convert.png",
              "caption": "Convert Colour: hsl(30 100% 50%) as hex first, then every notation and the nearest CSS name; the pane has the contrast on white and black"
            }
          ],
          "actions": [
            {
              "title": "Copy",
              "description": "The colour in the notation the `format` setting names; `cmd+c` always copies the hex.",
              "keys": "c, cmd+c"
            },
            {
              "title": "Pick Colour from Screen",
              "description": "Hides the panel and shows the system's loupe; the picked colour comes back into the picker (or, from the root row, onto the clipboard).",
              "keys": "p"
            },
            {
              "title": "Walk the colour",
              "description": "Hue on left/right, lightness on up/down, saturation or chroma on - and +; shift makes the step three to five times bigger.",
              "keys": "left, right, up, down, -, +"
            },
            {
              "title": "Type a notation",
              "description": "A digit or # opens the text field with that character; Enter applies, Escape closes it.",
              "keys": "0-9, #"
            },
            {
              "title": "Focus a row of tiles",
              "description": "Tab moves the focus from the swatch to the tints, the shades and each harmony; the arrows walk the row and Enter uses the tile.",
              "keys": "tab, shift+tab"
            },
            {
              "title": "Open in Picker",
              "description": "From a set tile, a history entry or a converter row: the picker on that colour.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "picker": {
            "title": "Colour Picker",
            "kind": "view",
            "rank": 0,
            "description": "The colour under the keys: every notation, tints, shades, harmonies, contrast and the nearest tokens; `p` picks from the screen, a digit types a notation.",
            "keys": [
              {
                "keys": "c",
                "title": "Copy in the chosen notation"
              },
              {
                "keys": "cmd+c",
                "title": "Copy hex"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Copy rgb (h hsl, o oklch, l lab, p display-p3, n the CSS name)"
              },
              {
                "keys": "p",
                "title": "Pick Colour from Screen"
              },
              {
                "keys": "left, right",
                "title": "Hue -5° / +5° (shift: 15°)"
              },
              {
                "keys": "up, down",
                "title": "Lighter / darker by 2 points (shift: 10)"
              },
              {
                "keys": "-, +",
                "title": "Less / more saturation (chroma in OKLCH)"
              },
              {
                "keys": "m",
                "title": "Edit in HSL or in OKLCH"
              },
              {
                "keys": "0-9, #",
                "title": "Type a notation into the search row; Enter applies, Escape closes"
              },
              {
                "keys": "tab, shift+tab",
                "title": "Focus the next / previous row of tiles; arrows walk it, Enter uses the tile"
              },
              {
                "keys": "h",
                "title": "History"
              },
              {
                "keys": "n",
                "title": "Named Colours"
              },
              {
                "keys": "u",
                "title": "Back to the previous colour"
              },
              {
                "keys": "r",
                "title": "A random colour"
              }
            ]
          },
          "colors": {
            "title": "Named Colours",
            "tier": "catalog",
            "kind": "grid",
            "rank": 1,
            "description": "The named sets as swatch tiles, one section per set, a filter per set; recently opened tiles first.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Picker"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy in the chosen notation"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy hex"
              },
              {
                "keys": "cmd+shift+n",
                "title": "Copy the token name (`slate-500`, `systemBlue`)"
              },
              {
                "keys": "cmd+i",
                "title": "The detail pane: notations, contrast, where the token is used"
              },
              {
                "keys": "tab",
                "title": "Next set"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in the grid.",
                "min": 4,
                "max": 16,
                "default": 8
              }
            ]
          },
          "history": {
            "title": "Colour History",
            "kind": "live",
            "remember": false,
            "rank": 2,
            "description": "Every picked and copied colour, newest first, with when and where from; Pick Colour from Screen at the top.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Picker (on the top row: pick from the screen)"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy in the chosen notation"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy hex"
              },
              {
                "keys": "cmd+d",
                "title": "Remove from History"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Clear History"
              }
            ]
          },
          "convert": {
            "title": "Convert Colour",
            "kind": "input",
            "rank": 3,
            "inline": true,
            "match": "^\\s*(#[0-9a-f]{3,8}|(rgba?|hsla?|hwb|oklch|oklab|lab|color)\\(.*\\)|[a-z]{3,20})\\s*$",
            "description": "Type a colour in any notation; the rows are its conversions. Enter opens the picker on it. At the root a hex, a function notation or a CSS name answers inline under a Convert Colour section.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Picker"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy the row"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/colors",
      "tagline": "Pick, type or walk a colour, then copy it in any notation",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/colors/screenshots/1-picker-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/1-picker.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/2-shades-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/2-shades.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/3-typing-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/3-typing.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/4-sets-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/4-sets.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/5-history-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/5-history.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/6-convert-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/6-convert.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/colors/screenshots/1-picker.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/2-shades.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/3-typing.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/4-sets.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/5-history.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/6-convert.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/colors/screenshots/1-picker-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/2-shades-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/3-typing-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/4-sets-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/5-history-dark.png",
        "https://pal.cagdas.io/extensions/colors/screenshots/6-convert-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "crossword",
      "kind": "registry",
      "title": "Crossword",
      "description": "Daily crosswords in the panel: Crosshare's English minis, and the Turkish papers' kare bulmaca from HaberTürk, Cumhuriyet and Sabah. Every key is saved, so you can leave mid-puzzle and pick up where you were.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰄹",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/crossword@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/crossword",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "crossword",
        "title": "Crossword",
        "description": "Daily crosswords in the panel: Crosshare's English minis, and the Turkish papers' kare bulmaca from HaberTürk, Cumhuriyet and Sabah. Every key is saved, so you can leave mid-puzzle and pick up where you were.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰄹",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "mini",
          "puzzle",
          "crosshare",
          "clues",
          "daily",
          "bulmaca",
          "kare bulmaca",
          "haberturk",
          "cumhuriyet",
          "sabah"
        ],
        "sync": {
          "counts": {
            "fields": {
              "crosshare": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "ms": "sum"
                }
              },
              "haberturk": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "ms": "sum"
                }
              },
              "cumhuriyet": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "ms": "sum"
                }
              },
              "sabah": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "ms": "sum"
                }
              }
            }
          },
          "best": {
            "fields": {
              "crosshare": "min",
              "haberturk": "min",
              "cumhuriyet": "min",
              "sabah": "min"
            }
          },
          "days": {
            "fields": {
              "crosshare": "union",
              "haberturk": "union",
              "cumhuriyet": "union",
              "sabah": "union"
            }
          },
          "seeded": "local"
        },
        "leaderboards": [
          {
            "id": "crosshare/*",
            "title": "Crosshare, {1}",
            "order": "asc",
            "format": "time",
            "min": 1,
            "max": 86400
          },
          {
            "id": "haberturk/*",
            "title": "HaberTürk, {1}",
            "order": "asc",
            "format": "time",
            "min": 1,
            "max": 86400
          },
          {
            "id": "cumhuriyet/*",
            "title": "Cumhuriyet, {1}",
            "order": "asc",
            "format": "time",
            "min": 1,
            "max": 86400
          },
          {
            "id": "sabah/*",
            "title": "Sabah, {1}",
            "order": "asc",
            "format": "time",
            "min": 1,
            "max": 86400
          }
        ],
        "settings": [
          {
            "kind": "select",
            "id": "source",
            "label": "Opens on",
            "description": "Whose puzzle the first open shows (when nothing is left half-done), and whose puzzle of the day the Now row offers. Browse has every source as a tab either way.",
            "options": [
              {
                "id": "crosshare",
                "title": "Crosshare: English minis"
              },
              {
                "id": "haberturk",
                "title": "HaberTürk: günlük kare bulmaca"
              },
              {
                "id": "cumhuriyet",
                "title": "Cumhuriyet: günlük kare bulmaca"
              },
              {
                "id": "sabah",
                "title": "Sabah: kare bulmaca archive (2024 to 2025)"
              }
            ],
            "default": "crosshare"
          },
          {
            "kind": "boolean",
            "id": "autocheck",
            "label": "Autocheck",
            "text": "Mark a wrong letter the moment it is typed",
            "description": "Also on ⌘K. A solve with autocheck on is marked as checked in the history.",
            "default": false
          },
          {
            "kind": "boolean",
            "id": "suggest",
            "label": "Today's mini in Now",
            "text": "A row in the root's Now section while today's mini is unsolved",
            "description": "Only once you have solved a puzzle, and gone as soon as today's is solved.",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "clock",
            "label": "Clock",
            "text": "Show the time while you play",
            "description": "Off hides the running time. Your times still count for stats and show when you finish. Also ⌘T or ⌘K in the game.",
            "default": true
          }
        ],
        "store": {
          "tagline": "Daily crosswords: Crosshare's minis and the Turkish papers' kare bulmaca",
          "category": "fun",
          "features": [
            "Today's Crosshare mini, or a kare bulmaca from HaberTürk, Cumhuriyet or Sabah; Next goes to another unplayed one",
            "The NYT Mini's keys: type to fill, `space` turns, `tab` walks the clues",
            "Turkish letters typed on a US keyboard: `c` where Ç goes shows Ç",
            "Check or reveal a square, a word or the grid; a clock that runs only while the grid is on screen",
            "A calendar of past puzzles per source, marked solved, started or new",
            "Stats per source: best and average times, daily streaks, a chart of recent solves",
            "A dated puzzle solved without a reveal goes on its own leaderboard; signed in to a pal account, the stats and streaks follow you to every machine"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-solving.png",
              "caption": "Today's mini mid-solve: the clue you are on above the lists, the crossing clue lit",
              "cover": [
                161,
                227,
                673,
                330
              ]
            },
            {
              "file": "2-solved.png",
              "caption": "Solved: the time, the best, the streak, Next puzzle on Enter"
            },
            {
              "file": "3-browse.png",
              "caption": "The daily minis month by month, solved and started marked"
            },
            {
              "file": "4-stats.png",
              "caption": "Stats: best and average, the streak, recent times"
            }
          ],
          "actions": [
            {
              "title": "Next puzzle",
              "description": "Another unplayed mini: today's if it is still open, then back through the dailies, then the newest minis.",
              "keys": "cmd+n"
            },
            {
              "title": "Skip this puzzle",
              "description": "Next, the first open and the Now row pass it by from then on; opening it from Browse takes the skip back.",
              "keys": "cmd+shift+n"
            },
            {
              "title": "Browse puzzles",
              "description": "The daily minis by month, or the newest minis.",
              "keys": "cmd+o"
            },
            {
              "title": "Stats",
              "description": "Times, streaks and the history.",
              "keys": "cmd+s"
            },
            {
              "title": "Check word",
              "description": "Also the square (⌘⌥E) and the grid (⌘G, or Enter once the grid is full but not right).",
              "keys": "cmd+e"
            },
            {
              "title": "Reveal word",
              "description": "Also the square (⌘⌥U) and the grid (⌘⇧U).",
              "keys": "cmd+u"
            },
            {
              "title": "Clear word",
              "description": "Also the grid (⌘⌥⌫).",
              "keys": "alt+backspace"
            },
            {
              "title": "Show every clue",
              "description": "Over a wide grid with no room for the lists beside it.",
              "keys": "cmd+l"
            },
            {
              "title": "Pause",
              "description": "Stops the clock and hides the grid.",
              "keys": "cmd+p"
            },
            {
              "title": "Hide the clock",
              "description": "No running time on screen; again to bring it back. Times still count.",
              "keys": "cmd+t"
            }
          ]
        },
        "palettes": {
          "crossword": {
            "kind": "view",
            "title": "Crossword",
            "description": "The puzzle left half-done, else today's of the source you chose. Escape leaves at any point; every key is saved.",
            "keys": [
              {
                "keys": "a",
                "title": "Type a letter: fills the square and moves on"
              },
              {
                "keys": "backspace",
                "title": "Clear the square, or step back and clear"
              },
              {
                "keys": "space",
                "title": "Turn: across or down"
              },
              {
                "keys": "tab",
                "title": "Next clue (shift+tab the previous one)"
              },
              {
                "keys": "up",
                "title": "Move (an arrow across the word turns first)"
              },
              {
                "keys": "cmd+e",
                "title": "Check word (cmd+alt+e square, cmd+g grid)"
              },
              {
                "keys": "cmd+u",
                "title": "Reveal word (cmd+alt+u square, cmd+shift+u grid)"
              },
              {
                "keys": "cmd+n",
                "title": "Next puzzle"
              },
              {
                "keys": "cmd+o",
                "title": "Browse puzzles"
              },
              {
                "keys": "?",
                "title": "Every key"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/crossword",
      "tagline": "Daily crosswords: Crosshare's minis and the Turkish papers' kare bulmaca",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/crossword/screenshots/1-solving-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/1-solving.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/2-solved-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/2-solved.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/3-browse-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/3-browse.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/4-stats-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/4-stats.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/crossword/screenshots/1-solving.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/2-solved.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/3-browse.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/4-stats.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/crossword/screenshots/1-solving-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/2-solved-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/3-browse-dark.png",
        "https://pal.cagdas.io/extensions/crossword/screenshots/4-stats-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "diff",
      "kind": "registry",
      "title": "Diff",
      "description": "Compare the two things you copied last, with changed lines tinted and the differing words marked. Also diff the clipboard against a selection, any two history entries, or two files.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰢪",
          "bg": "orange"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/diff@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/diff",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "diff",
        "title": "Diff",
        "description": "Compare the two things you copied last, with changed lines tinted and the differing words marked. Also diff the clipboard against a selection, any two history entries, or two files.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰢪",
            "bg": "orange"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "diffy",
          "compare"
        ],
        "settings": [
          {
            "kind": "select",
            "id": "tool",
            "label": "External tool",
            "description": "What `o` opens the two sides in. Auto takes the first installed of VS Code (`code --diff`), kitty (`+kitten diff`), FileMerge (`opendiff`, with Xcode) and Meld.",
            "options": [
              {
                "id": "auto",
                "title": "Auto (VS Code, kitty, FileMerge, Meld)"
              },
              {
                "id": "code",
                "title": "VS Code (code --diff)"
              },
              {
                "id": "kitty",
                "title": "kitty (kitten diff)"
              },
              {
                "id": "opendiff",
                "title": "FileMerge (opendiff)"
              },
              {
                "id": "meld",
                "title": "Meld"
              },
              {
                "id": "custom",
                "title": "Custom command"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "text",
            "id": "tool_command",
            "label": "Custom command",
            "description": "With the custom tool: the command line, `{left}` and `{right}` standing for the two files (a quoted argument stays whole).",
            "placeholder": "nvim -d {left} {right}",
            "default": ""
          }
        ],
        "store": {
          "tagline": "Diff the two things you just copied",
          "category": "developer",
          "features": [
            "Opens on the two newest text copies, the older on the left",
            "Other pairs: the clipboard against the selection (`e`), two history entries (`h`), two files (`f`)",
            "Changed words marked inside each line; unified or side by side (`s`); `w` ignores whitespace",
            "Unchanged stretches fold away; `tab` walks them, `space` expands one",
            "`enter` copies the unified diff; `o` opens both sides in VS Code, kitty, FileMerge or Meld"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Copy unified diff",
              "keys": "enter"
            },
            {
              "title": "Open in external tool",
              "description": "The two sides as files in VS Code, kitty, FileMerge, Meld or the custom command.",
              "keys": "o"
            },
            {
              "title": "Side by side / Unified",
              "keys": "s"
            },
            {
              "title": "Ignore whitespace / Mind whitespace",
              "description": "Leading and trailing whitespace on a line does not count.",
              "keys": "w"
            },
            {
              "title": "Swap sides",
              "keys": "x"
            },
            {
              "title": "Copy left text",
              "keys": "l"
            },
            {
              "title": "Copy right text",
              "keys": "r"
            },
            {
              "title": "Expand the fold under the cursor",
              "description": "`tab` and `shift+tab` move the cursor over the folds; `a` expands every fold; a click expands one.",
              "keys": "space"
            },
            {
              "title": "Diff the two newest copies",
              "keys": "n"
            },
            {
              "title": "Clipboard vs selection",
              "keys": "e"
            },
            {
              "title": "Pick two from history…",
              "keys": "h"
            },
            {
              "title": "Two files…",
              "keys": "f"
            }
          ],
          "screenshots": [
            {
              "file": "1-unified.png",
              "caption": "The two newest copies diffed: the older on the left, the words that changed marked, unchanged runs folded"
            },
            {
              "file": "2-side.png",
              "caption": "s puts the sides next to each other"
            },
            {
              "file": "3-actions.png",
              "caption": "Every key on ⌘K: copy the unified diff or either side, open both in your diff tool, other sources"
            },
            {
              "file": "4-history.png",
              "caption": "Any two from the clipboard history: pick the left, then the right, or mark two and press Enter"
            }
          ]
        },
        "links": {
          "clipboard": {
            "description": "Diff the two newest text copies in the clipboard history"
          },
          "selection": {
            "description": "Diff the clipboard against the selection in the app in front"
          },
          "files": {
            "description": "Diff two files",
            "params": {
              "left": {
                "description": "The left file's path (~ allowed)",
                "required": true
              },
              "right": {
                "description": "The right file's path",
                "required": true
              }
            }
          },
          "text": {
            "description": "Diff two texts given in the link",
            "params": {
              "left": {
                "description": "The left text",
                "required": true
              },
              "right": {
                "description": "The right text",
                "required": true
              },
              "left_label": {
                "description": "What to call the left side"
              },
              "right_label": {
                "description": "What to call the right side"
              }
            }
          },
          "history": {
            "description": "Diff two clipboard history entries by id",
            "params": {
              "left": {
                "description": "The left entry's id",
                "required": true,
                "type": "number"
              },
              "right": {
                "description": "The right entry's id",
                "required": true,
                "type": "number"
              }
            }
          }
        },
        "palettes": {
          "diff": {
            "title": "Diff",
            "kind": "view",
            "description": "The two newest copies diffed; keys for other pairs, side by side, whitespace, the folds, the tool.",
            "keywords": [
              "diffy",
              "compare"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the unified diff"
              },
              {
                "keys": "o",
                "title": "Open both sides in the external tool"
              },
              {
                "keys": "s",
                "title": "Side by side, or unified"
              },
              {
                "keys": "w",
                "title": "Ignore whitespace, or mind it"
              },
              {
                "keys": "x",
                "title": "Swap the sides"
              },
              {
                "keys": "l",
                "title": "Copy the left text"
              },
              {
                "keys": "r",
                "title": "Copy the right text"
              },
              {
                "keys": "tab",
                "title": "Next fold (shift+tab: previous)"
              },
              {
                "keys": "space",
                "title": "Expand the fold under the cursor"
              },
              {
                "keys": "a",
                "title": "Expand every fold"
              },
              {
                "keys": "n",
                "title": "The two newest copies"
              },
              {
                "keys": "e",
                "title": "The clipboard against the selection"
              },
              {
                "keys": "h",
                "title": "Pick two entries from the history"
              },
              {
                "keys": "f",
                "title": "Two files"
              }
            ]
          },
          "pick": {
            "title": "Diff from History",
            "kind": "input",
            "description": "The clipboard history's text entries: pick the left side, then the right; or mark two and press Enter.",
            "keys": [
              {
                "keys": "enter",
                "title": "Pick this side (with two marked: diff them)"
              },
              {
                "keys": "tab",
                "title": "Mark the entry (x with nothing typed)"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/diff",
      "tagline": "Diff the two things you just copied",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/diff/screenshots/1-unified-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/1-unified.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/2-side-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/2-side.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/4-history-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/4-history.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/diff/screenshots/1-unified.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/2-side.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/4-history.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/diff/screenshots/1-unified-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/2-side-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/diff/screenshots/4-history-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "clipboard",
          "url": "pal://diff/clipboard",
          "cli": "pal call diff/clipboard",
          "description": "Diff the two newest text copies in the clipboard history",
          "params": []
        },
        {
          "route": "selection",
          "url": "pal://diff/selection",
          "cli": "pal call diff/selection",
          "description": "Diff the clipboard against the selection in the app in front",
          "params": []
        },
        {
          "route": "files",
          "url": "pal://diff/files?left=\u003cleft\u003e\u0026right=\u003cright\u003e",
          "cli": "pal call diff/files left=\u003cleft\u003e right=\u003cright\u003e",
          "description": "Diff two files",
          "params": [
            {
              "name": "left",
              "description": "The left file's path (~ allowed)",
              "required": true
            },
            {
              "name": "right",
              "description": "The right file's path",
              "required": true
            }
          ]
        },
        {
          "route": "text",
          "url": "pal://diff/text?left=\u003cleft\u003e\u0026right=\u003cright\u003e",
          "cli": "pal call diff/text left=\u003cleft\u003e right=\u003cright\u003e",
          "description": "Diff two texts given in the link",
          "params": [
            {
              "name": "left",
              "description": "The left text",
              "required": true
            },
            {
              "name": "right",
              "description": "The right text",
              "required": true
            },
            {
              "name": "left_label",
              "description": "What to call the left side"
            },
            {
              "name": "right_label",
              "description": "What to call the right side"
            }
          ]
        },
        {
          "route": "history",
          "url": "pal://diff/history?left=\u003cleft\u003e\u0026right=\u003cright\u003e",
          "cli": "pal call diff/history left=\u003cleft\u003e right=\u003cright\u003e",
          "description": "Diff two clipboard history entries by id",
          "params": [
            {
              "name": "left",
              "description": "The left entry's id",
              "required": true,
              "type": "number"
            },
            {
              "name": "right",
              "description": "The right entry's id",
              "required": true,
              "type": "number"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "displays",
      "kind": "bundled",
      "title": "Displays",
      "description": "Every display with its mode and brightness: change resolution, scaling, rotation and mirroring, set an external monitor's brightness and input source, and save arrangements to switch between.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰍹",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/displays@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/displays",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "displays",
        "title": "Displays",
        "description": "Every display with its mode and brightness: change resolution, scaling, rotation and mirroring, set an external monitor's brightness and input source, and save arrangements to switch between.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰍹",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "screen",
          "monitor",
          "brightness",
          "resolution"
        ],
        "settings": [
          {
            "kind": "number",
            "id": "step",
            "label": "Brightness step",
            "description": "What one press of the arrow keys, a scroll on the bar item or a `+10`-style link moves a level by, in percent. Shift with an arrow always moves 1%.",
            "min": 1,
            "max": 25,
            "step": 1,
            "unit": "%",
            "default": 5
          },
          {
            "kind": "boolean",
            "id": "input_alt",
            "label": "LG input codes",
            "text": "Use the alternate DDC input addressing (LG and some others)",
            "description": "Most monitors take the standard VCP 60 codes for their inputs (DisplayPort 1 is 15, HDMI 1 is 17). LG's take 208 and 144 instead; turn this on if switching the input does nothing.",
            "default": false
          }
        ],
        "store": {
          "tagline": "Resolution, brightness, rotation and input source for every display",
          "category": "system",
          "features": [
            "One row per display with its resolution, refresh rate, rotation and brightness",
            "Brightness, contrast and volume as sliders, for external monitors too (over DDC)",
            "Switch the input source of an external monitor",
            "Change the resolution with an easy undo, rotate, mirror or make a display the main one",
            "Save the arrangement under a name and apply it again from the list, the bar or a link",
            "Each tool it uses is optional; a row says what to install when one is missing"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Every display with its mode and brightness; Night Shift, Sleep displays and the saved arrangements below"
            },
            {
              "file": "2-display.png",
              "caption": "Enter on a monitor: brightness, contrast and volume over DDC, the input source, modes, mirroring and rotation"
            },
            {
              "file": "3-brightness.png",
              "caption": "A control opens as a slider: the arrows move it by the step, the digits jump to 10 to 100%"
            },
            {
              "file": "4-modes.png",
              "caption": "Every mode the monitor takes, HiDPI first and the current one tagged; a change keeps Undo one row away"
            },
            {
              "file": "5-actions.png",
              "caption": "Set the brightness from the bar's text, make a display main or copy its id for a link"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the external monitor's brightness, a scroll on it moves it by the step",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: a card per display with its mode and a brightness slider",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                668
              ]
            },
            {
              "file": "bar-popover-panel.png",
              "caption": "↓ moves to the next display: the arrows and the digits now set the built-in panel",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                668
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the sun and the level as its label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "Drills into the display: its controls, modes and arrangement.",
              "keys": "enter"
            },
            {
              "title": "Set brightness",
              "description": "The percent typed in the bar (or +10 / -10).",
              "keys": "cmd+b"
            },
            {
              "title": "Make main",
              "description": "Moves the arrangement so this display is at (0,0).",
              "keys": "cmd+shift+m"
            }
          ]
        },
        "palettes": {
          "displays": {
            "title": "Displays",
            "kind": "live",
            "description": "Every display with its mode and brightness, the arrangement presets, Night Shift and Sleep displays; Enter drills into a display's controls.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the display, apply a preset, run a row"
              },
              {
                "keys": "cmd+b",
                "title": "Set the brightness to the percent typed in the bar"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Make the display the main one"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the display's id, for links"
              },
              {
                "keys": "cmd+r",
                "title": "Rename a preset"
              },
              {
                "keys": "cmd+backspace",
                "title": "Delete a preset"
              }
            ]
          }
        },
        "links": {
          "brightness": {
            "description": "Set a display's brightness",
            "params": {
              "value": {
                "description": "A percent (50), or a step (+10, -5)",
                "required": true
              },
              "display": {
                "description": "main, external, builtin, a display id or a name; the bar item's display otherwise"
              }
            }
          },
          "contrast": {
            "description": "Set an external monitor's contrast over DDC",
            "params": {
              "value": {
                "description": "A percent (50), or a step (+10, -5)",
                "required": true
              },
              "display": {
                "description": "external, a display id or a name; the first external otherwise"
              }
            }
          },
          "volume": {
            "description": "Set an external monitor's speaker volume over DDC",
            "params": {
              "value": {
                "description": "A percent (50), or a step (+10, -5)",
                "required": true
              },
              "display": {
                "description": "external, a display id or a name; the first external otherwise"
              }
            }
          },
          "input": {
            "description": "Switch an external monitor's input source over DDC",
            "params": {
              "source": {
                "description": "hdmi1, hdmi2, dp1, dp2, usbc, or a raw VCP 60 code",
                "required": true
              },
              "display": {
                "description": "external, a display id or a name; the first external otherwise"
              }
            }
          },
          "mode": {
            "description": "Set a display's resolution (displayplacer, or the compositor on Linux)",
            "params": {
              "mode": {
                "description": "A mode number from the palette, or 1800x1169, 1800x1169@60, 2560x1440 hidpi, 3024x1964 native",
                "required": true
              },
              "display": {
                "description": "main, external, builtin, a display id or a name; the main display otherwise"
              }
            }
          },
          "preset": {
            "description": "Apply a saved arrangement preset",
            "params": {
              "name": {
                "description": "The preset's name",
                "required": true
              }
            }
          },
          "night-shift": {
            "description": "Night Shift on, off or toggled (the nightlight CLI)",
            "params": {
              "state": {
                "description": "on, off or toggle; toggle otherwise"
              }
            }
          }
        },
        "states": {
          "brightness": {
            "description": "The bar item's display's brightness, percent; unset while unreadable",
            "kind": "number"
          },
          "external": {
            "description": "How many external displays are connected",
            "kind": "number"
          },
          "count": {
            "description": "How many displays are online",
            "kind": "number"
          },
          "settable": {
            "description": "Whether any display's brightness can be set from pal",
            "kind": "boolean"
          }
        },
        "bar": {
          "brightness": {
            "title": "Brightness",
            "description": "The external display's brightness (or the main or built-in one's, by the setting), with a slider per display in the popover, a scroll on the item moving it by the step. Hidden while only the built-in display is there, whose keys already set it, and while nothing installed can set any display: its rules, which Settings \u003e Bar lets you turn off to keep the item.",
            "refresh": {
              "every": 60,
              "on": [
                "wake",
                "show"
              ]
            },
            "settings": [
              {
                "kind": "select",
                "id": "display",
                "label": "Display on the bar",
                "description": "Whose brightness the bar item shows: the first external display (the built-in one has keys of its own), the main display, or the built-in one.",
                "options": [
                  {
                    "id": "external",
                    "title": "The external display"
                  },
                  {
                    "id": "main",
                    "title": "The main display"
                  },
                  {
                    "id": "builtin",
                    "title": "The built-in display"
                  }
                ],
                "default": "external"
              }
            ],
            "mocks": {
              "laptop": {
                "title": "Only the built-in display, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰃟",
                    "title": "50%",
                    "tooltip": "Built-in Retina Display · 50%"
                  }
                }
              },
              "external": {
                "title": "An external display connected",
                "item": {
                  "icon": "󰃠",
                  "title": "70%",
                  "tooltip": "Aurora 27Q · 70% · 2560×1440 @ 60 Hz · HiDPI"
                }
              },
              "dim": {
                "title": "Dimmed",
                "item": {
                  "icon": "󰃞",
                  "title": "15%",
                  "tooltip": "Aurora 27Q · 15% · 2560×1440 @ 60 Hz · HiDPI"
                }
              },
              "unreadable": {
                "title": "External connected, no DDC tool",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰃟",
                    "tooltip": "Aurora 27Q: install m1ddc to set its brightness"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the display in pal"
              },
              {
                "keys": "up / down",
                "title": "Move between displays"
              },
              {
                "keys": "left / right",
                "title": "Brightness down / up by the step"
              },
              {
                "keys": "shift+left / shift+right",
                "title": "Brightness by 1%"
              },
              {
                "keys": "1…9, 0",
                "title": "10…90%, 100%"
              },
              {
                "keys": "n",
                "title": "Night Shift on / off"
              },
              {
                "keys": "p",
                "title": "Open the Displays palette"
              }
            ],
            "rules": [
              {
                "id": "laptop",
                "when": "displays.external == 0",
                "description": "Only the built-in display: its keyboard keys set it. Off, and the item stays with the built-in display's level.",
                "hidden": true
              },
              {
                "id": "unsettable",
                "when": "not displays.settable",
                "description": "Nothing installed can set any display's brightness: nothing to open a slider on.",
                "hidden": true
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/displays",
      "tagline": "Resolution, brightness, rotation and input source for every display",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/displays/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/2-display-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/2-display.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/3-brightness-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/3-brightness.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/4-modes-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/4-modes.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/5-actions-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/5-actions.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover-panel-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover-panel.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/displays/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/2-display.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/3-brightness.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/4-modes.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/5-actions.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover-panel.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/displays/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/2-display-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/3-brightness-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/4-modes-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/5-actions-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover-panel-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/displays/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "brightness",
          "title": "Brightness",
          "description": "The external display's brightness (or the main or built-in one's, by the setting), with a slider per display in the popover, a scroll on the item moving it by the step. Hidden while only the built-in display is there, whose keys already set it, and while nothing installed can set any display: its rules, which Settings \u003e Bar lets you turn off to keep the item.",
          "refresh": {
            "every": 60,
            "on": [
              "wake",
              "show"
            ]
          },
          "refresh_words": "every 1 min, on wake, when the panel shows"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "brightness",
          "url": "pal://displays/brightness?value=\u003cvalue\u003e",
          "cli": "pal call displays/brightness value=\u003cvalue\u003e",
          "description": "Set a display's brightness",
          "params": [
            {
              "name": "value",
              "description": "A percent (50), or a step (+10, -5)",
              "required": true
            },
            {
              "name": "display",
              "description": "main, external, builtin, a display id or a name; the bar item's display otherwise"
            }
          ]
        },
        {
          "route": "contrast",
          "url": "pal://displays/contrast?value=\u003cvalue\u003e",
          "cli": "pal call displays/contrast value=\u003cvalue\u003e",
          "description": "Set an external monitor's contrast over DDC",
          "params": [
            {
              "name": "value",
              "description": "A percent (50), or a step (+10, -5)",
              "required": true
            },
            {
              "name": "display",
              "description": "external, a display id or a name; the first external otherwise"
            }
          ]
        },
        {
          "route": "volume",
          "url": "pal://displays/volume?value=\u003cvalue\u003e",
          "cli": "pal call displays/volume value=\u003cvalue\u003e",
          "description": "Set an external monitor's speaker volume over DDC",
          "params": [
            {
              "name": "value",
              "description": "A percent (50), or a step (+10, -5)",
              "required": true
            },
            {
              "name": "display",
              "description": "external, a display id or a name; the first external otherwise"
            }
          ]
        },
        {
          "route": "input",
          "url": "pal://displays/input?source=\u003csource\u003e",
          "cli": "pal call displays/input source=\u003csource\u003e",
          "description": "Switch an external monitor's input source over DDC",
          "params": [
            {
              "name": "source",
              "description": "hdmi1, hdmi2, dp1, dp2, usbc, or a raw VCP 60 code",
              "required": true
            },
            {
              "name": "display",
              "description": "external, a display id or a name; the first external otherwise"
            }
          ]
        },
        {
          "route": "mode",
          "url": "pal://displays/mode?mode=\u003cmode\u003e",
          "cli": "pal call displays/mode mode=\u003cmode\u003e",
          "description": "Set a display's resolution (displayplacer, or the compositor on Linux)",
          "params": [
            {
              "name": "mode",
              "description": "A mode number from the palette, or 1800x1169, 1800x1169@60, 2560x1440 hidpi, 3024x1964 native",
              "required": true
            },
            {
              "name": "display",
              "description": "main, external, builtin, a display id or a name; the main display otherwise"
            }
          ]
        },
        {
          "route": "preset",
          "url": "pal://displays/preset?name=\u003cname\u003e",
          "cli": "pal call displays/preset name=\u003cname\u003e",
          "description": "Apply a saved arrangement preset",
          "params": [
            {
              "name": "name",
              "description": "The preset's name",
              "required": true
            }
          ]
        },
        {
          "route": "night-shift",
          "url": "pal://displays/night-shift",
          "cli": "pal call displays/night-shift",
          "description": "Night Shift on, off or toggled (the nightlight CLI)",
          "params": [
            {
              "name": "state",
              "description": "on, off or toggle; toggle otherwise"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "docker",
      "kind": "registry",
      "title": "Docker",
      "description": "Your Docker containers, images and Compose projects in one list: start and stop containers, read their logs in the panel, or open a shell in a terminal.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z",
          "box": 24,
          "bg": "#2496ED"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/docker@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/docker",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "docker",
        "title": "Docker",
        "description": "Your Docker containers, images and Compose projects in one list: start and stop containers, read their logs in the panel, or open a shell in a terminal.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z",
            "box": 24,
            "bg": "#2496ED"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "binary",
            "label": "Binary",
            "description": "The CLI to run: docker, or podman (its docker-compatible commands are what is used).",
            "placeholder": "docker",
            "default": "docker"
          },
          {
            "kind": "number",
            "id": "ttl",
            "label": "Refresh after",
            "description": "Seconds a listing stays good for: the palettes list again on show only once the rows are older than this. Read when the extension loads.",
            "min": 0,
            "max": 3600,
            "unit": "s",
            "default": 10
          },
          {
            "kind": "select",
            "id": "terminal",
            "label": "Terminal (macOS)",
            "description": "Which terminal Shell opens. Auto picks the first installed of kitty, Ghostty, Alacritty, iTerm2, Terminal. On Linux $TERMINAL, else kitty, foot, alacritty, xterm.",
            "options": [
              {
                "id": "auto",
                "title": "Auto"
              },
              {
                "id": "kitty",
                "title": "kitty"
              },
              {
                "id": "Terminal",
                "title": "Terminal"
              },
              {
                "id": "iTerm2",
                "title": "iTerm2"
              },
              {
                "id": "Ghostty",
                "title": "Ghostty"
              },
              {
                "id": "Alacritty",
                "title": "Alacritty"
              }
            ],
            "default": "auto"
          }
        ],
        "store": {
          "tagline": "Start, stop, log and shell into containers from the panel",
          "category": "developer",
          "features": [
            "Every container, running ones first, with its image, ports and state; `cmd+i` shows it as a page",
            "`enter` starts or stops a container (stopping asks first)",
            "`cmd+l` shows its recent logs in the panel; `cmd+t` opens a shell in a terminal",
            "Run an image with an optional name and ports",
            "Compose projects: up, down, restart, logs, open the folder",
            "Works with Podman too (a setting)"
          ],
          "permissions": [
            "docker",
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-containers.png",
              "caption": "Containers, running first, with their ports (a stopped one's status) and a state tag"
            },
            {
              "file": "2-actions.png",
              "caption": "What a running container can do: stop, logs, shell, restart, remove"
            },
            {
              "file": "3-logs.png",
              "caption": "The last log lines of a container, opened in the panel (cmd+L): nginx starting yesterday, today's requests under it"
            },
            {
              "file": "4-run.png",
              "caption": "Running an image: the name and the ports, then docker run -d"
            },
            {
              "file": "5-detail.png",
              "caption": "A container's detail (cmd+I): its Compose project and image, the name, its state and status, then id, command, ports, mounts and networks"
            }
          ],
          "actions": [
            {
              "title": "Stop",
              "description": "A running container; asks first.",
              "keys": "enter"
            },
            {
              "title": "Start",
              "description": "A stopped container.",
              "keys": "enter"
            },
            {
              "title": "Logs",
              "description": "The last 200 lines (or the count typed in the bar), stdout and stderr, in the panel.",
              "keys": "cmd+l"
            },
            {
              "title": "Shell",
              "description": "A terminal running docker exec (bash when the image has it, sh otherwise), or the command typed in the bar, kept open until Enter.",
              "keys": "cmd+t"
            },
            {
              "title": "Restart",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Remove",
              "description": "docker rm -f, docker rmi or compose down; asks first.",
              "keys": "cmd+d"
            },
            {
              "title": "Copy id",
              "keys": "cmd+c"
            },
            {
              "title": "Run",
              "description": "An image: the bar takes a name and host:container ports (both optional, comma separated ports), then docker run -d.",
              "keys": "enter"
            },
            {
              "title": "Up",
              "description": "A Compose project: compose up -d.",
              "keys": "enter"
            },
            {
              "title": "Down",
              "description": "Stops and removes the project's containers and networks; asks first.",
              "keys": "cmd+d"
            },
            {
              "title": "Open project folder",
              "keys": "cmd+o"
            }
          ]
        },
        "palettes": {
          "docker": {
            "title": "Docker Containers",
            "kind": "live",
            "lazy": true,
            "description": "Every container, running first: start, stop, restart, logs, a shell, remove.",
            "keys": [
              {
                "keys": "enter",
                "title": "Stop a running container, start a stopped one"
              },
              {
                "keys": "cmd+l",
                "title": "Logs (the line count typed in the bar; 200 when blank)"
              },
              {
                "keys": "cmd+t",
                "title": "Shell in a terminal, or the command typed in the bar"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Restart"
              },
              {
                "keys": "cmd+d",
                "title": "Remove"
              },
              {
                "keys": "cmd+c",
                "title": "Copy id"
              }
            ]
          },
          "images": {
            "title": "Docker Images",
            "kind": "live",
            "lazy": true,
            "description": "Local images: run one (name and ports typed in the bar), remove, copy the id.",
            "keys": [
              {
                "keys": "enter",
                "title": "Run, with the name and ports typed in the bar (both optional)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy id"
              },
              {
                "keys": "cmd+d",
                "title": "Remove"
              }
            ]
          },
          "compose": {
            "title": "Compose Projects",
            "kind": "live",
            "lazy": true,
            "description": "Compose projects docker knows of: up, down, restart, logs.",
            "keys": [
              {
                "keys": "enter",
                "title": "Up"
              },
              {
                "keys": "cmd+l",
                "title": "Logs"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Restart"
              },
              {
                "keys": "cmd+d",
                "title": "Down"
              },
              {
                "keys": "cmd+o",
                "title": "Open project folder"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/docker",
      "tagline": "Start, stop, log and shell into containers from the panel",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/docker/screenshots/1-containers-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/1-containers.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/3-logs-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/3-logs.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/4-run-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/4-run.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/docker/screenshots/1-containers.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/3-logs.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/4-run.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/docker/screenshots/1-containers-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/3-logs-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/4-run-dark.png",
        "https://pal.cagdas.io/extensions/docker/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "downloads",
      "kind": "bundled",
      "title": "Downloads",
      "description": "Your Downloads folder newest first, with thumbnails and downloads still in progress: open, reveal, move, rename or trash files, and clear out old ones in one go.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰇚",
          "bg": "cyan"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/downloads@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/downloads",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "downloads",
        "title": "Downloads",
        "description": "Your Downloads folder newest first, with thumbnails and downloads still in progress: open, reveal, move, rename or trash files, and clear out old ones in one go.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰇚",
            "bg": "cyan"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "folder",
            "label": "Folder",
            "description": "The downloads folder; `~` is expanded.",
            "pick": "folder",
            "placeholder": "~/Downloads",
            "default": "~/Downloads"
          },
          {
            "kind": "boolean",
            "id": "browser_folders",
            "label": "Browser folders",
            "text": "Also list the download folder each browser is set to, when it is another one (Chrome, Brave, Edge, Vivaldi, Arc, Firefox)",
            "default": true
          },
          {
            "kind": "number",
            "id": "limit",
            "label": "Rows",
            "description": "At most this many files, the newest.",
            "min": 10,
            "max": 2000,
            "unit": "rows",
            "default": 200
          },
          {
            "kind": "boolean",
            "id": "thumbnails",
            "label": "Thumbnails",
            "text": "Show a 64 px preview of images and PDFs instead of the kind glyph (made once with sips or ImageMagick, cached)",
            "default": true
          },
          {
            "kind": "number",
            "id": "clear_days",
            "label": "Clear older than",
            "description": "The age the Clear row moves to the Trash.",
            "min": 1,
            "max": 365,
            "unit": "days",
            "default": 30
          }
        ],
        "store": {
          "tagline": "Your downloads newest first: open, reveal, trash, tidy",
          "category": "productivity",
          "features": [
            "Downloads newest first, grouped by day, with size, age and a thumbnail for images and PDFs",
            "Downloads in progress at the top with their speed",
            "Open, reveal, copy the file or its path, or move it to the Trash (asks first)",
            "Move a file to a folder or rename it; `tab` marks several at once",
            "Clear everything older than 30 days in one row",
            "Your newest download shows in the main list for ten minutes"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-downloads.png",
              "caption": "The folder newest first: a download coming in, then Today, Yesterday, This week, Older with sizes and ages"
            },
            {
              "file": "2-detail.png",
              "caption": "The detail pane: the folder over the name, its kind and size, and the page the file came from"
            },
            {
              "file": "3-actions.png",
              "caption": "What a download can do: open, reveal, copy, move, rename, trash"
            },
            {
              "file": "4-move.png",
              "caption": "cmd+m moves it: a form with the target folder, created when it is missing"
            },
            {
              "file": "5-marked.png",
              "caption": "Three rows marked with shift+down (Tab marks too): open, reveal, copy or trash them at once"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "The system opener; on marked rows, every one.",
              "keys": "enter"
            },
            {
              "title": "Reveal in Finder",
              "description": "Show in file manager on Linux.",
              "keys": "cmd+enter"
            },
            {
              "title": "Quick Look",
              "description": "macOS only.",
              "keys": "cmd+y"
            },
            {
              "title": "Copy file",
              "description": "The file itself onto the clipboard: a paste in Finder copies it.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy path",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Move to folder…",
              "description": "A form for the target folder; `~` is expanded, a missing folder is created.",
              "keys": "cmd+m"
            },
            {
              "title": "Rename",
              "description": "The name typed in the bar; a form with the current name when blank.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Move to Trash",
              "description": "Asks first; marked rows together.",
              "keys": "cmd+d"
            },
            {
              "title": "Move them to the Trash",
              "description": "On the Clear row: every file older than the setting, asks first.",
              "keys": "enter"
            },
            {
              "title": "Open the folder",
              "description": "On the Open Downloads row.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "downloads": {
            "title": "Downloads",
            "kind": "live",
            "remember": false,
            "tier": "primary",
            "description": "The downloads folder (and the browsers' when different) newest first with size, kind or thumbnail and age, a download in progress first; the last rows clear what is old and open the folder.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the file"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+y",
                "title": "Quick Look (macOS)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the file"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+m",
                "title": "Move to a folder"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Rename to the name typed in the bar"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash"
              },
              {
                "keys": "tab",
                "title": "Mark the row for a multi pick"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/downloads",
      "tagline": "Your downloads newest first: open, reveal, trash, tidy",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/downloads/screenshots/1-downloads-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/1-downloads.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/4-move-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/4-move.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/5-marked-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/5-marked.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/downloads/screenshots/1-downloads.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/4-move.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/5-marked.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/downloads/screenshots/1-downloads-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/4-move-dark.png",
        "https://pal.cagdas.io/extensions/downloads/screenshots/5-marked-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "dpi",
      "kind": "registry",
      "title": "DPI Bypass",
      "description": "Turns the `dpi` script's censorship bypass on and off, with a shield on the menu bar while it is on. Shows the status, repairs a half-applied state, and runs an end-to-end test.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰕥",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/dpi@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/dpi",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "dpi",
        "title": "DPI Bypass",
        "description": "Turns the `dpi` script's censorship bypass on and off, with a shield on the menu bar while it is on. Shows the status, repairs a half-applied state, and runs an end-to-end test.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰕥",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "dpi",
          "bypass",
          "byedpi",
          "zapret",
          "censorship"
        ],
        "settings": [
          {
            "kind": "path",
            "id": "tool",
            "label": "Tool",
            "description": "The dpi script: a name on PATH or a path. It lives at ~/.local/bin/dpi; that directory is looked in when the name is not on PATH.",
            "pick": "file",
            "default": "dpi"
          },
          {
            "kind": "list",
            "id": "test_urls",
            "label": "Test urls",
            "placeholder": "https://discord.com/ = blocked",
            "description": "What the test curls: `url`, or `url = blocked` (the bypass must get it through) / `url = control` (a site that must keep working). Without a role the first two are blocked and the rest controls, as the script's list reads.",
            "default": [
              "https://discord.com/ = blocked",
              "https://www.roblox.com/ = blocked",
              "https://www.enpara.com/ = control",
              "https://www.raycast.com/ = control",
              "https://slack.com/ = control",
              "https://example.com/ = control"
            ]
          },
          {
            "kind": "list",
            "id": "dns",
            "label": "Override DNS",
            "placeholder": "1.1.1.1",
            "description": "The resolvers `dpi on` sets on macOS (the script's DNS_ON), so the status can tell a full bypass from a partial one: the proxy up with the DNS still the ISP's is partial. Empty: DNS is not judged.",
            "default": [
              "1.1.1.1",
              "9.9.9.9"
            ]
          }
        ],
        "store": {
          "tagline": "The DPI bypass on and off, with a shield on the bar",
          "category": "system",
          "features": [
            "Turn on and Turn off as rows; the state stays at the top of the panel while on",
            "A half-applied state shows amber with the reason, and a Repair row fixes it",
            "A test that tries each site through the bypass and shows which get through",
            "A shield on the menu bar while on; its popover toggles, tests and repairs",
            "Links like `pal://dpi/toggle` for a keybind",
            "Uses byedpi on macOS and zapret with dnscrypt-proxy on Linux; the script does the work"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-on.png",
              "caption": "The bypass on: Turn off leads, then the status, the test, the log, the build and a copy of the status"
            },
            {
              "file": "2-status.png",
              "caption": "⌘I on the status: what the script printed, and the proxy, the network service, the DNS and the SOCKS proxy it names"
            },
            {
              "file": "3-test.png",
              "caption": "The test: a curl per url through the proxy, the blocked sites and the controls with their codes and times"
            },
            {
              "file": "4-partial.png",
              "caption": "Half on: amber with the reason, and a Repair row that turns it off and on again"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar only while the bypass is on: a shield",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-partial.png",
              "caption": "Half on: the shield turns amber and half full",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the status with its facts; Enter turns it off, t tests it",
              "kind": "bar",
              "box": [
                452,
                64,
                840,
                626
              ]
            },
            {
              "file": "bar-popover-test.png",
              "caption": "t runs the test in the popover: each url's code lands under the card",
              "kind": "bar",
              "box": [
                452,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-partial.png",
              "caption": "Half on: the reason on the card and r to repair",
              "kind": "bar",
              "box": [
                452,
                64,
                840,
                626
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the shield while the bypass is on",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Turn on / Turn off",
              "description": "Runs the script; the HUD says its line.",
              "keys": "enter"
            },
            {
              "title": "Test the bypass",
              "description": "The test level, from any row.",
              "keys": "cmd+t"
            },
            {
              "title": "Repair",
              "description": "Off, then on; on the Turn off row while partial.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Copy the status",
              "description": "The script's status output.",
              "keys": "cmd+c"
            }
          ]
        },
        "links": {
          "toggle": {
            "description": "Turn the bypass on, or off while it is on (the script's toggle)"
          },
          "on": {
            "description": "Turn the bypass on"
          },
          "off": {
            "description": "Turn the bypass off; the script restores the previous settings"
          },
          "test": {
            "description": "Open the panel on the test level; the test runs at once"
          },
          "status": {
            "description": "Open the DPI Bypass palette"
          }
        },
        "palettes": {
          "dpi": {
            "title": "DPI Bypass",
            "kind": "live",
            "description": "Turn the bypass on or off, repair a half-on one, read the status, run the test, open the log, build byedpi.",
            "keys": [
              {
                "keys": "enter",
                "title": "Turn the bypass on or off; on Status, copy it; on Test, run it"
              },
              {
                "keys": "cmd+t",
                "title": "Test the bypass"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Repair: off, then on (while partial)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the status"
              }
            ]
          },
          "test": {
            "title": "Bypass Test",
            "kind": "view",
            "description": "The bypass tested end to end: a row per url with its HTTP code, the time and whether it is a blocked site or a control, landing one by one.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the url under the cursor"
              },
              {
                "keys": "c",
                "title": "Copy the row's line"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the whole report"
              },
              {
                "keys": "cmd+r",
                "title": "Run the test again"
              },
              {
                "keys": "up",
                "title": "Move the cursor (down, j, k too)"
              }
            ]
          }
        },
        "states": {
          "on": {
            "description": "The bypass is on, or partly on",
            "kind": "boolean"
          },
          "state": {
            "description": "off, on or partial",
            "kind": "string"
          },
          "service": {
            "description": "The network service the proxy is set on (macOS), or the units (Linux)",
            "kind": "string"
          }
        },
        "bar": {
          "bypass": {
            "title": "DPI Bypass",
            "description": "A shield while the bypass is on, hidden while off by its rule (`show = \"always\"` keeps a muted one), amber while only half of it is in effect. The popover: the status card with the facts, Enter turns it on or off, `t` runs the test and shows its rows in place, `r` repairs, `c` copies the status, `l` opens the log, `o` the palette.",
            "refresh": {
              "every": 60,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "rules": [
              {
                "id": "off",
                "when": "dpi.state == 'off'",
                "description": "Off: nothing to say.",
                "hidden": true
              },
              {
                "id": "partial",
                "when": "dpi.state == 'partial'",
                "description": "Only half of the bypass is in effect.",
                "color": "amber"
              }
            ],
            "mocks": {
              "off": {
                "title": "Off, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰒙",
                    "tooltip": "Bypass off\nWi-Fi as before, byedpi down"
                  }
                }
              },
              "on": {
                "title": "On, over Wi-Fi",
                "item": {
                  "icon": "󰕥",
                  "tooltip": "Bypass on\nWi-Fi -\u003e socks5://127.0.0.1:1080, dns 1.1.1.1 9.9.9.9"
                }
              },
              "partial": {
                "title": "Partly on",
                "item": {
                  "icon": "󰞀",
                  "color": "amber",
                  "tooltip": "Bypass partly on\nProxy up (pid 4242), but SOCKS off and DNS not overridden"
                }
              },
              "linux": {
                "title": "On, Linux",
                "item": {
                  "icon": "󰕥",
                  "tooltip": "Bypass on\nzapret + dnscrypt-proxy up, resolver -\u003e 127.0.0.1"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Turn the bypass on or off"
              },
              {
                "keys": "t",
                "title": "Test the bypass; the rows land in the popover"
              },
              {
                "keys": "r",
                "title": "Repair: off, then on"
              },
              {
                "keys": "c",
                "title": "Copy the status"
              },
              {
                "keys": "l",
                "title": "Open the log (macOS)"
              },
              {
                "keys": "o",
                "title": "Open the DPI Bypass palette"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/dpi",
      "tagline": "The DPI bypass on and off, with a shield on the bar",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/dpi/screenshots/1-on-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/1-on.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/2-status-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/2-status.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/3-test-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/3-test.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/4-partial-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/4-partial.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar-partial-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar-partial.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-partial-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-partial.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-test-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-test.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/dpi/screenshots/1-on.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/2-status.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/3-test.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/4-partial.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar-partial.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-partial.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-test.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/dpi/screenshots/1-on-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/2-status-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/3-test-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/4-partial-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar-partial-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-partial-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-test-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/dpi/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "bypass",
          "title": "DPI Bypass",
          "description": "A shield while the bypass is on, hidden while off by its rule (`show = \"always\"` keeps a muted one), amber while only half of it is in effect. The popover: the status card with the facts, Enter turns it on or off, `t` runs the test and shows its rows in place, `r` repairs, `c` copies the status, `l` opens the log, `o` the palette.",
          "refresh": {
            "every": 60,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "toggle",
          "url": "pal://dpi/toggle",
          "cli": "pal call dpi/toggle",
          "description": "Turn the bypass on, or off while it is on (the script's toggle)",
          "params": []
        },
        {
          "route": "on",
          "url": "pal://dpi/on",
          "cli": "pal call dpi/on",
          "description": "Turn the bypass on",
          "params": []
        },
        {
          "route": "off",
          "url": "pal://dpi/off",
          "cli": "pal call dpi/off",
          "description": "Turn the bypass off; the script restores the previous settings",
          "params": []
        },
        {
          "route": "test",
          "url": "pal://dpi/test",
          "cli": "pal call dpi/test",
          "description": "Open the panel on the test level; the test runs at once",
          "params": []
        },
        {
          "route": "status",
          "url": "pal://dpi/status",
          "cli": "pal call dpi/status",
          "description": "Open the DPI Bypass palette",
          "params": []
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "emoji",
      "kind": "bundled",
      "title": "Emoji",
      "description": "An emoji picker: every emoji in a grid, recently used first, found by name, keyword or :shortcode:. Copy or paste it in your skin tone.",
      "version": "0.2.0",
      "icon": {
        "tile": {
          "glyph": "󰱱",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/emoji@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/emoji",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "emoji",
        "title": "Emoji",
        "description": "An emoji picker: every emoji in a grid, recently used first, found by name, keyword or :shortcode:. Copy or paste it in your skin tone.",
        "version": "0.2.0",
        "icon": {
          "tile": {
            "glyph": "󰱱",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "skin_tone",
            "label": "Skin tone",
            "description": "Applied to the emoji that take one (hands, people) when shown, copied and pasted.",
            "options": [
              {
                "id": "none",
                "title": "None (yellow)"
              },
              {
                "id": "light",
                "title": "Light"
              },
              {
                "id": "medium-light",
                "title": "Medium-light"
              },
              {
                "id": "medium",
                "title": "Medium"
              },
              {
                "id": "medium-dark",
                "title": "Medium-dark"
              },
              {
                "id": "dark",
                "title": "Dark"
              }
            ],
            "default": "none"
          },
          {
            "kind": "boolean",
            "id": "paste_by_default",
            "label": "Paste on Enter",
            "text": "Enter pastes the emoji into the app in front; ⌘Enter copies it",
            "description": "Off, Enter copies and ⌘Enter pastes. Pasting needs Accessibility on macOS.",
            "default": false
          },
          {
            "kind": "list",
            "id": "keywords",
            "label": "Your keywords",
            "description": "Extra search words per emoji, one line each: a shortcode or the emoji, a colon, then the words (`rocket: ship deploy`, `🎉: party woo`). A line naming no emoji is ignored.",
            "placeholder": "rocket: ship deploy",
            "default": []
          }
        ],
        "store": {
          "tagline": "Every emoji in a grid; copy or paste it, or its :shortcode:",
          "category": "reference",
          "features": [
            "Every emoji in a grid by category, the ones you used lately first",
            "Search by name, keyword or shortcode: `thumbs`, `celebrate`, `:thumbs_up:`",
            "Add your own keywords: `ship` and `deploy` for the rocket",
            "`enter` copies, `cmd+enter` pastes into the app in front (or the other way round, a setting)",
            "`cmd+shift+c` copies the `:shortcode:`",
            "A skin tone setting, applied everywhere it can be"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-grid.png",
              "caption": "The grid: Recently used, then Smileys \u0026 Emotion and the other groups"
            },
            {
              "file": "2-search.png",
              "caption": "Searching by keyword narrows the tiles across every group"
            },
            {
              "file": "3-actions.png",
              "caption": "Copy, paste, or copy the :shortcode:"
            }
          ],
          "actions": [
            {
              "title": "Copy emoji",
              "keys": "enter"
            },
            {
              "title": "Paste emoji",
              "description": "Into the app that was in front; needs Accessibility on macOS.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy shortcode",
              "description": "`:thumbs_up:`",
              "keys": "cmd+shift+c"
            }
          ]
        },
        "palettes": {
          "emoji": {
            "title": "Emoji",
            "tier": "catalog",
            "kind": "grid",
            "ttl": 30,
            "description": "Every emoji in the bundled list, by category.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy emoji"
              },
              {
                "keys": "cmd+enter",
                "title": "Paste emoji"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy shortcode"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in the grid.",
                "min": 4,
                "max": 16,
                "default": 10
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/emoji",
      "tagline": "Every emoji in a grid; copy or paste it, or its :shortcode:",
      "category": "reference",
      "screenshots": [
        "https://pal.cagdas.io/extensions/emoji/screenshots/1-grid-dark.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/1-grid.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/3-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/emoji/screenshots/1-grid.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/3-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/emoji/screenshots/1-grid-dark.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/emoji/screenshots/3-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "files",
      "kind": "bundled",
      "title": "Files",
      "description": "Find files by name or contents through the system's search index, browse folders, and act on files: open, reveal, Quick Look, rename, move, compress or trash. Recent files show before you type, and on macOS what you selected in Finder.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰉋",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/files@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/files",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "files",
        "title": "Files",
        "description": "Find files by name or contents through the system's search index, browse folders, and act on files: open, reveal, Quick Look, rename, move, compress or trash. Recent files show before you type, and on macOS what you selected in Finder.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰉋",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "list",
            "id": "folders",
            "local": true,
            "label": "Folders",
            "description": "Where to search. `~` is expanded.",
            "placeholder": "~/Documents",
            "default": [
              "~"
            ]
          },
          {
            "kind": "number",
            "id": "limit",
            "label": "Results",
            "description": "At most this many rows per query.",
            "min": 1,
            "max": 500,
            "unit": "rows",
            "default": 50
          },
          {
            "kind": "boolean",
            "id": "show_hidden",
            "label": "Hidden files",
            "text": "List files and folders whose name starts with a dot",
            "default": false
          },
          {
            "kind": "boolean",
            "id": "content_search",
            "label": "Search contents",
            "text": "Also list files whose text contains the query, under the name matches (a query starting with ' or content: searches contents only)",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "ocr_concealed",
            "label": "OCR copies are private",
            "text": "Text read from an image (Copy text) is kept out of clipboard history",
            "default": false
          },
          {
            "kind": "list",
            "id": "exclude",
            "label": "Exclude",
            "description": "Folders skipped below the search folders, by name (`node_modules`) or a short path (`Library/Caches`).",
            "placeholder": "node_modules",
            "default": [
              "node_modules",
              ".cache",
              "Library/Caches",
              "target"
            ]
          },
          {
            "kind": "text",
            "id": "terminal",
            "label": "Terminal",
            "description": "What Open in Terminal opens: `Terminal` (default), `iTerm`, `kitty`, `Alacritty`, `WezTerm`, `Ghostty`, or any app name (`open -na \u003cname\u003e --args -e ...`); on Linux a command name (`kitty`, `foot`, `alacritty`, `wezterm`, `ghostty`, ...), else `$TERMINAL`, else the first of those installed.",
            "placeholder": "Terminal",
            "default": ""
          }
        ],
        "store": {
          "tagline": "Find, browse and act on files, recent ones before you type",
          "category": "productivity",
          "features": [
            "Search by name through Spotlight on macOS or `fd`/`locate` on Linux; by contents with a `'` prefix",
            "Recent files and the Finder selection before you type anything",
            "`enter` on a folder browses it, sorted by name, date or size",
            "Open with, reveal, Quick Look, copy the path or file, open in a terminal",
            "Rename, move, copy, compress or trash, one file or several at once",
            "Copy the text out of an image or PDF (`cmd+shift+t`)"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-search.png",
              "caption": "Part of a file name typed: the matches under the configured folders, size and date on the right"
            },
            {
              "file": "2-detail.png",
              "caption": "The detail pane on a text file: its folder, name and kind, the size, its first lines"
            },
            {
              "file": "3-open-with.png",
              "caption": "Open with…: the apps registered for the file, the default tagged"
            },
            {
              "file": "4-recent.png",
              "caption": "Recent Files: what was used in the last seven days, newest first"
            },
            {
              "file": "5-browse.png",
              "caption": "Browsing ~/proj: the crumb is the folder, .. leads, the dropdown sorts by name, date or size"
            },
            {
              "file": "6-rename.png",
              "caption": "Rename (cmd+shift+R) is a form over the name, in the same folder; Move to and Copy to open the same way"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "The system opener.",
              "keys": "enter"
            },
            {
              "title": "Browse",
              "description": "On a folder: its contents as a level, `→` too. `←` or Backspace goes up.",
              "keys": "enter, right"
            },
            {
              "title": "Reveal in Finder",
              "description": "Show in file manager on Linux.",
              "keys": "cmd+enter"
            },
            {
              "title": "Quick Look",
              "description": "macOS only; every marked row at once, arrows between them.",
              "keys": "cmd+y"
            },
            {
              "title": "Open with…",
              "description": "A level of the apps registered for the file.",
              "keys": "cmd+o"
            },
            {
              "title": "Copy path",
              "keys": "cmd+c"
            },
            {
              "title": "Copy file",
              "description": "The file itself onto the clipboard: a paste in Finder copies it.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Open in Terminal",
              "description": "A terminal window in the folder (a file's folder), the app the `terminal` setting names.",
              "keys": "cmd+t"
            },
            {
              "title": "Rename",
              "description": "The name typed in the bar, in the same folder; a form with the current name when blank.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Move to…",
              "description": "A form; the folder it goes to, made when missing.",
              "keys": "cmd+m"
            },
            {
              "title": "Copy to…",
              "description": "A form; a copy under the same name in that folder.",
              "keys": "cmd+alt+c"
            },
            {
              "title": "Compress",
              "description": "A zip next to the file, or one zip of every marked row, named after the first.",
              "keys": "cmd+shift+z"
            },
            {
              "title": "Move to Trash",
              "description": "Asks first.",
              "keys": "cmd+d"
            },
            {
              "title": "Show hidden files",
              "description": "In a browsed folder: flips the `show_hidden` setting.",
              "keys": "cmd+."
            }
          ]
        },
        "palettes": {
          "files": {
            "title": "Files",
            "dialog": true,
            "kind": "input",
            "inline": true,
            "match": "^\\s*(~|/)",
            "fallback": "Search Files for “{query}”",
            "description": "Type part of a file name; rows are the matches under the configured folders. Before you type: the recently used files. A path (`~/Down`, `/usr/local`) lists the file or its completions, at the root too, and a path ending in `/` lists that folder whole; Enter on a folder browses it. A root query nothing matched gets a Search Files fallback row.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the file, browse a folder"
              },
              {
                "keys": "right",
                "title": "Browse a folder"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+y",
                "title": "Quick Look (macOS)"
              },
              {
                "keys": "cmd+o",
                "title": "Open with another app"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the file"
              },
              {
                "keys": "cmd+t",
                "title": "Open in a terminal"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Rename to the name typed in the bar"
              },
              {
                "keys": "cmd+m",
                "title": "Move to a folder"
              },
              {
                "keys": "cmd+alt+c",
                "title": "Copy to a folder"
              },
              {
                "keys": "cmd+shift+z",
                "title": "Compress to a zip"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash"
              }
            ]
          },
          "browse": {
            "title": "Browse Folder",
            "kind": "input",
            "description": "A folder's contents, pushed by Browse on a folder row (or by typing a path ending in `/`): a `..` row first, then the entries under the dropdown's sort (name, date, size), hidden ones with `show_hidden`, at most 500. The crumb is the folder; typing filters by name.",
            "keys": [
              {
                "keys": "enter",
                "title": "Browse a folder, open a file"
              },
              {
                "keys": "right",
                "title": "Browse the folder under the cursor"
              },
              {
                "keys": "left, backspace",
                "title": "Go up (while nothing is typed)"
              },
              {
                "keys": "tab",
                "title": "Cycle the sort: name, date, size"
              },
              {
                "keys": "cmd+.",
                "title": "Show or hide hidden files"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+o",
                "title": "Open with another app"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the file"
              },
              {
                "keys": "cmd+t",
                "title": "Open in a terminal"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Rename to the name typed in the bar"
              },
              {
                "keys": "cmd+m",
                "title": "Move to a folder"
              },
              {
                "keys": "cmd+alt+c",
                "title": "Copy to a folder"
              },
              {
                "keys": "cmd+shift+z",
                "title": "Compress to a zip"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash"
              }
            ]
          },
          "selection": {
            "title": "Finder Selection",
            "kind": "input",
            "description": "The files selected in Finder (the front window's, or the Desktop's), each with the file actions; several are led by an \"N items\" row whose actions run on all of them. The same rows lead the empty root under \"Selected in Finder\" whenever pal opens over Finder with something marked. macOS only; the palette says why when Finder is not in front or nothing is selected.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the file, browse a folder"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+y",
                "title": "Quick Look (macOS)"
              },
              {
                "keys": "cmd+o",
                "title": "Open with another app"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the file"
              },
              {
                "keys": "cmd+t",
                "title": "Open in a terminal"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Rename to the name typed in the bar"
              },
              {
                "keys": "cmd+m",
                "title": "Move to a folder"
              },
              {
                "keys": "cmd+alt+c",
                "title": "Copy to a folder"
              },
              {
                "keys": "cmd+shift+z",
                "title": "Compress to a zip"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash"
              }
            ]
          },
          "recent": {
            "title": "Recent Files",
            "tier": "primary",
            "kind": "live",
            "remember": false,
            "ttl": 60,
            "description": "Files used in the last seven days under the configured folders, newest first.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the file"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+y",
                "title": "Quick Look (macOS)"
              },
              {
                "keys": "cmd+o",
                "title": "Open with another app"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the file"
              },
              {
                "keys": "cmd+t",
                "title": "Open in a terminal"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Rename to the name typed in the bar"
              },
              {
                "keys": "cmd+m",
                "title": "Move to a folder"
              },
              {
                "keys": "cmd+alt+c",
                "title": "Copy to a folder"
              },
              {
                "keys": "cmd+shift+z",
                "title": "Compress to a zip"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/files",
      "tagline": "Find, browse and act on files, recent ones before you type",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/files/screenshots/1-search-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/1-search.png",
        "https://pal.cagdas.io/extensions/files/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/files/screenshots/3-open-with-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/3-open-with.png",
        "https://pal.cagdas.io/extensions/files/screenshots/4-recent-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/4-recent.png",
        "https://pal.cagdas.io/extensions/files/screenshots/5-browse-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/5-browse.png",
        "https://pal.cagdas.io/extensions/files/screenshots/6-rename-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/6-rename.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/files/screenshots/1-search.png",
        "https://pal.cagdas.io/extensions/files/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/files/screenshots/3-open-with.png",
        "https://pal.cagdas.io/extensions/files/screenshots/4-recent.png",
        "https://pal.cagdas.io/extensions/files/screenshots/5-browse.png",
        "https://pal.cagdas.io/extensions/files/screenshots/6-rename.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/files/screenshots/1-search-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/3-open-with-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/4-recent-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/5-browse-dark.png",
        "https://pal.cagdas.io/extensions/files/screenshots/6-rename-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "flash",
      "kind": "registry",
      "title": "Flash",
      "description": "Plays Flash games in pal with Ruffle, the Flash Player emulator: the games of the Flash games collection, each one a package of its own that runs on this. Saves and scores follow you like any pal game's.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M9.5 1 3 9h4.5L6.5 15 13 7H8.5z",
          "bg": "red"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/flash@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/flash",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "flash",
        "title": "Flash",
        "description": "Plays Flash games in pal with Ruffle, the Flash Player emulator: the games of the Flash games collection, each one a package of its own that runs on this. Saves and scores follow you like any pal game's.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M9.5 1 3 9h4.5L6.5 15 13 7H8.5z",
            "bg": "red"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "flash",
          "ruffle",
          "swf",
          "games"
        ],
        "store": {
          "tagline": "Flash games in pal, played by Ruffle",
          "category": "fun",
          "features": [
            "Ruffle, the open source Flash Player emulator, in every Flash game's page; no plugin",
            "ActionScript 1, 2 and 3 games, scaled to fill the panel with their shape kept",
            "A game's saves are kept in pal and follow you to your other machines when you sign in",
            "Scores go to the game's leaderboards when it keeps one",
            "Games pause when the panel hides and save what they had",
            "Its palette is the Flash games as a showcase, like Games; until the collection is added it offers to, and asks for its password"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-add.png",
              "caption": "Until the Flash games collection is added, the palette offers to add it; it asks for a password, then its games show here as in Games"
            },
            {
              "file": "2-actions.png",
              "caption": "One thing to do until then: add the collection"
            }
          ]
        },
        "palettes": {
          "flash": {
            "title": "Flash games",
            "kind": "view",
            "description": "The Flash games as a showcase, like Games: Enter plays one, or installs it first. Until the Flash games collection is added, it offers to add it."
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/flash",
      "tagline": "Flash games in pal, played by Ruffle",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/flash/screenshots/1-add-dark.png",
        "https://pal.cagdas.io/extensions/flash/screenshots/1-add.png",
        "https://pal.cagdas.io/extensions/flash/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/flash/screenshots/2-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/flash/screenshots/1-add.png",
        "https://pal.cagdas.io/extensions/flash/screenshots/2-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/flash/screenshots/1-add-dark.png",
        "https://pal.cagdas.io/extensions/flash/screenshots/2-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "flashcards",
      "kind": "registry",
      "title": "Flashcards",
      "description": "Spaced repetition for the spare minute: flip a card, throw it right if you knew it and left if you did not, and the scheduler Anki uses decides when it comes back. Starts with the most common Spanish words, and takes any Anki deck or a file of your own.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰘸",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/flashcards@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/flashcards",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "flashcards",
        "title": "Flashcards",
        "description": "Spaced repetition for the spare minute: flip a card, throw it right if you knew it and left if you did not, and the scheduler Anki uses decides when it comes back. Starts with the most common Spanish words, and takes any Anki deck or a file of your own.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰘸",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "learn",
          "study",
          "practice",
          "cards",
          "srs",
          "anki",
          "spanish",
          "vocabulary"
        ],
        "store": {
          "tagline": "Spaced-repetition flashcards: Spanish to start, any deck of your own",
          "category": "productivity",
          "features": [
            "`space` flips a card; → if you knew it, ← if not (or drag it)",
            "FSRS, Anki's scheduler, decides when each card comes back; every answer is saved at once",
            "Short sessions with a summary, then a drill of the ones you missed",
            "Type the word once you recognise it; a missed accent counts and is shown",
            "A daily goal, a streak and stats with a heatmap",
            "Browse and add AnkiWeb's shared decks, or import `.apkg`, TSV, CSV or JSON"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-card.png",
              "caption": "A card turned over: the meaning, an example with the word marked, the article coloured by gender, and when each answer brings it back"
            },
            {
              "file": "2-typed.png",
              "caption": "The other way, typed: an accent left off counts, and shows where"
            },
            {
              "file": "3-goal.png",
              "caption": "The day's twentieth card: the goal met, the streak goes on"
            },
            {
              "file": "4-stats.png",
              "caption": "Stats: the streak, the heatmap, the week ahead, each pack"
            },
            {
              "file": "5-welcome.png",
              "caption": "The first run: pick the packs to practise, or bring your own"
            }
          ]
        },
        "settings": [
          {
            "kind": "number",
            "id": "new_per_day",
            "label": "New cards a day",
            "description": "How many cards you have never seen come in each day, across every pack you practise. Fewer new cards means fewer reviews later; Learn more on the day's summary adds ten for today.",
            "default": 15,
            "min": 0,
            "max": 200,
            "step": 5
          },
          {
            "kind": "number",
            "id": "session",
            "label": "Cards per session",
            "description": "A session is this many answers, then a short summary with Keep going: a size that fits the wait for a build. 0 runs until nothing is due.",
            "default": 10,
            "min": 0,
            "max": 200,
            "step": 5,
            "unit": "cards"
          },
          {
            "kind": "number",
            "id": "goal",
            "label": "Daily goal",
            "description": "Answers a day that fill the ring and keep the streak going.",
            "default": 20,
            "min": 1,
            "max": 500,
            "step": 5,
            "unit": "cards"
          },
          {
            "kind": "select",
            "id": "retention",
            "label": "Remember",
            "description": "How much of what is due you should still remember when it comes back. Higher means more reviews: 90% is what FSRS recommends.",
            "options": [
              {
                "id": "0.8",
                "title": "80%: fewer reviews"
              },
              {
                "id": "0.85",
                "title": "85%"
              },
              {
                "id": "0.9",
                "title": "90% (recommended)"
              },
              {
                "id": "0.95",
                "title": "95%: many more reviews"
              }
            ],
            "default": "0.9"
          },
          {
            "kind": "select",
            "id": "typing",
            "label": "Type the answer",
            "description": "Reverse cards (English to Spanish) ask you to type the answer, which is how a word moves from recognised to produced. Always types on every card; Never flips every card.",
            "options": [
              {
                "id": "reverse",
                "title": "On reverse cards"
              },
              {
                "id": "always",
                "title": "Always"
              },
              {
                "id": "never",
                "title": "Never: flip every card"
              }
            ],
            "default": "reverse"
          },
          {
            "kind": "select",
            "id": "speak",
            "label": "Say it aloud",
            "description": "The word in the language you are learning, with the system's voice for it (macOS: say; Linux: spd-say or espeak-ng). Tab says it again whatever this is.",
            "options": [
              {
                "id": "auto",
                "title": "When it shows"
              },
              {
                "id": "key",
                "title": "Only on Tab"
              },
              {
                "id": "off",
                "title": "Off"
              }
            ],
            "default": "key"
          },
          {
            "kind": "text",
            "id": "voice",
            "label": "Voice",
            "description": "A voice by name (macOS: Mónica, Paulina; `say -v ?` lists them). Empty picks the system's first voice for the pack's language.",
            "default": "",
            "placeholder": "Automatic"
          },
          {
            "kind": "select",
            "id": "buttons",
            "label": "Buttons",
            "description": "Two: Didn't know and Knew it, which is all the scheduler needs. Four adds Barely and Too easy, as Anki's Hard and Easy.",
            "options": [
              {
                "id": "two",
                "title": "Didn't know, Knew it"
              },
              {
                "id": "four",
                "title": "Didn't know, Barely, Knew it, Too easy"
              }
            ],
            "default": "two"
          },
          {
            "kind": "boolean",
            "id": "sounds",
            "label": "Sounds",
            "text": "A soft tone for each answer and for the goal",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "suggest",
            "label": "On opening pal",
            "text": "A row for the cards due at the top of the empty panel",
            "default": true
          }
        ],
        "palettes": {
          "flashcards": {
            "kind": "view",
            "title": "Flashcards",
            "description": "Study what is due across the packs you practise; the day's summary when you are done.",
            "keywords": [
              "flashcards",
              "study",
              "review",
              "learn",
              "practice"
            ],
            "keys": [
              {
                "keys": "?",
                "title": "Every key, for where you are"
              },
              {
                "keys": "space",
                "title": "Flip the card; flipped, Knew it (or what the typed answer earned)"
              },
              {
                "keys": "right",
                "title": "Knew it: the card flies right, back later"
              },
              {
                "keys": "left",
                "title": "Didn't know: the card flies left, back in a minute"
              },
              {
                "keys": "enter",
                "title": "On a typed card: check it (empty: show the answer)"
              },
              {
                "keys": "tab",
                "title": "Say it; on a typed card, the next letter (shift+tab: the example)"
              },
              {
                "keys": "cmd+z",
                "title": "Undo the last answer"
              },
              {
                "keys": "cmd+e",
                "title": "Write your own meaning for this card"
              },
              {
                "keys": "s",
                "title": "Stats: streak, heatmap, the week ahead, each pack"
              },
              {
                "keys": "d",
                "title": "On the summary: drill this session's misses"
              },
              {
                "keys": "1",
                "title": "With four buttons: Didn't know, then 2 Barely, 3 Knew it, 4 Too easy"
              }
            ]
          },
          "flashcard-packs": {
            "kind": "live",
            "title": "Flashcard Packs",
            "description": "Every pack with how much of it you have mastered: study one, add it to practice or take it out, drill its weak cards.",
            "keywords": [
              "flashcards",
              "decks",
              "packs"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Study this pack"
              },
              {
                "keys": "cmd+enter",
                "title": "Add it to practice, or stop practising it (progress is kept)"
              },
              {
                "keys": "cmd+r",
                "title": "The refresher for this pack"
              }
            ]
          },
          "flashcard-add": {
            "kind": "input",
            "title": "Add Flashcard",
            "description": "Type front = back (gato = cat): the card goes into My cards, practised with the rest.",
            "keywords": [
              "flashcard",
              "card",
              "new"
            ]
          },
          "flashcard-anki": {
            "kind": "input",
            "title": "Browse Anki Decks",
            "description": "Search AnkiWeb's shared decks: rating, cards, audio and pictures on each row, the description and sample cards beside it; Enter downloads the deck into your practice.",
            "keywords": [
              "anki",
              "ankiweb",
              "decks",
              "flashcards"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Add to Flashcards (downloads it, then it joins your practice); added: study it"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the deck's page on AnkiWeb"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/flashcards",
      "tagline": "Spaced-repetition flashcards: Spanish to start, any deck of your own",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/flashcards/screenshots/1-card-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/1-card.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/2-typed-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/2-typed.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/3-goal-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/3-goal.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/4-stats-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/4-stats.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/5-welcome-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/5-welcome.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/flashcards/screenshots/1-card.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/2-typed.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/3-goal.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/4-stats.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/5-welcome.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/flashcards/screenshots/1-card-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/2-typed-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/3-goal-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/4-stats-dark.png",
        "https://pal.cagdas.io/extensions/flashcards/screenshots/5-welcome-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "games",
      "kind": "bundled",
      "title": "Games",
      "description": "Every game in one showcase, the installed ones and the ones you can still get, and their leaderboards. Enter opens a game, or installs it first and then opens it.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰊗",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/games@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/games",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "games",
        "title": "Games",
        "description": "Every game in one showcase, the installed ones and the ones you can still get, and their leaderboards. Enter opens a game, or installs it first and then opens it.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰊗",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "play",
          "fun",
          "game"
        ],
        "sync": {
          "hide_anon": "latest"
        },
        "store": {
          "tagline": "Every game in one showcase, one Enter away",
          "category": "fun",
          "features": [
            "The game you are on at the top: its own screenshot, its tagline and what it is",
            "Every game's cover under it in a grid of five, two rows at a time; the arrows walk it, a letter jumps to the next game starting with it",
            "What came out in the last week comes first, marked New; then your games, then the ones you have not installed, each by name",
            "`enter` opens a game, or installs it, waits for it to load and opens it",
            "`cmd+l` on a game shows its leaderboards: a tab per board, all time, this week or today, your own row marked, anonymous players hidden with `a`",
            "A failed install says why on the game; `enter` tries again"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-showcase.png",
              "caption": "What came out in the last week leads, marked New, then your games and the rest, each as a close-up of the game"
            },
            {
              "file": "2-not-installed.png",
              "caption": "A game you do not have yet, marked Not installed: Enter installs it and starts it"
            },
            {
              "file": "3-leaderboards.png",
              "caption": "A game's leaderboards: today's Wordle, fewest guesses first, anonymous players marked and your own row ringed"
            }
          ],
          "actions": [
            {
              "title": "Play",
              "description": "Opens the game.",
              "keys": "enter"
            },
            {
              "title": "Install and play",
              "description": "On a game not installed: installs it from its registry, waits for it to load, opens it.",
              "keys": "enter"
            },
            {
              "title": "Next game",
              "description": "Moves along the grid (`left` or `shift+tab` go back, `up` and `down` a row); a letter jumps to the next game starting with it.",
              "keys": "right"
            },
            {
              "title": "Leaderboards",
              "description": "The game's boards: `left` and `right` walk them, `p` the period, `a` hides anonymous players, `s` signs in when you are signed out.",
              "keys": "cmd+l"
            }
          ]
        },
        "palettes": {
          "games": {
            "title": "Games",
            "kind": "view",
            "description": "Every game, installed or on offer, as a showcase; Enter opens it, installing it first when needed.",
            "keys": [
              {
                "keys": "enter",
                "title": "Play"
              },
              {
                "keys": "right",
                "title": "Next game (left for the previous, up and down a row)"
              },
              {
                "keys": "cmd+l",
                "title": "Leaderboards"
              }
            ]
          },
          "leaderboards": {
            "title": "Leaderboards",
            "kind": "view",
            "description": "A game's leaderboards: a tab per board, the period, anonymous players shown or hidden. Opens on the last game looked at; G for another.",
            "keys": [
              {
                "keys": "right",
                "title": "Next board (left for the previous)"
              },
              {
                "keys": "p",
                "title": "All time, this week or today"
              },
              {
                "keys": "a",
                "title": "Hide or show anonymous players"
              },
              {
                "keys": "s",
                "title": "Sign in to put your scores here"
              },
              {
                "keys": "g",
                "title": "Another game's leaderboards"
              },
              {
                "keys": "enter",
                "title": "Play the game"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/games",
      "tagline": "Every game in one showcase, one Enter away",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/games/screenshots/1-showcase-dark.png",
        "https://pal.cagdas.io/extensions/games/screenshots/1-showcase.png",
        "https://pal.cagdas.io/extensions/games/screenshots/2-not-installed-dark.png",
        "https://pal.cagdas.io/extensions/games/screenshots/2-not-installed.png",
        "https://pal.cagdas.io/extensions/games/screenshots/3-leaderboards-dark.png",
        "https://pal.cagdas.io/extensions/games/screenshots/3-leaderboards.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/games/screenshots/1-showcase.png",
        "https://pal.cagdas.io/extensions/games/screenshots/2-not-installed.png",
        "https://pal.cagdas.io/extensions/games/screenshots/3-leaderboards.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/games/screenshots/1-showcase-dark.png",
        "https://pal.cagdas.io/extensions/games/screenshots/2-not-installed-dark.png",
        "https://pal.cagdas.io/extensions/games/screenshots/3-leaderboards-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "generate",
      "kind": "bundled",
      "title": "Generate",
      "description": "UUIDs, passwords, passphrases, random numbers, hashes, encodings, lorem ipsum, colours and QR codes, and a JWT taken apart. Every value copies on Enter.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰝮",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/generate@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/generate",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "generate",
        "title": "Generate",
        "description": "UUIDs, passwords, passphrases, random numbers, hashes, encodings, lorem ipsum, colours and QR codes, and a JWT taken apart. Every value copies on Enter.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰝮",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "number",
            "id": "password_length",
            "label": "Password length",
            "description": "Characters in a generated password; `password 32` in the panel overrides it for one listing.",
            "min": 4,
            "max": 256,
            "unit": "characters",
            "default": 20
          },
          {
            "kind": "select",
            "id": "password_charset",
            "label": "Password characters",
            "description": "What a password is drawn from; a word after `password` (`password 16 alnum`) overrides it for one listing.",
            "options": [
              {
                "id": "full",
                "title": "Letters, digits and symbols"
              },
              {
                "id": "alnum",
                "title": "Letters and digits"
              },
              {
                "id": "letters",
                "title": "Letters only"
              },
              {
                "id": "digits",
                "title": "Digits only (a PIN)"
              }
            ],
            "default": "full"
          },
          {
            "kind": "number",
            "id": "passphrase_words",
            "label": "Passphrase words",
            "description": "Words in a passphrase, from a list of 2551 common five-letter words (about 11 bits each); `passphrase 7` overrides it for one listing.",
            "min": 2,
            "max": 20,
            "unit": "words",
            "default": 5
          },
          {
            "kind": "text",
            "id": "passphrase_separator",
            "label": "Passphrase separator",
            "description": "What goes between the words.",
            "placeholder": "-",
            "default": "-"
          }
        ],
        "store": {
          "tagline": "UUIDs, passwords, hashes, base64, lorem ipsum, QR codes and JWTs",
          "category": "developer",
          "features": [
            "A fresh value of everything before you type: UUID v4 and v7, ULID, Nano ID, a password, a passphrase, random bytes, lorem ipsum, a colour",
            "A word and a number narrow it: `password 32 alnum`, `passphrase 7`, `number 1-6`, `lorem 3 paragraphs`",
            "Hash or encode the text you type, or the clipboard: `sha256`, `md5`, `base64`, `url`, `hex`, `decode`",
            "`qr \u003ctext\u003e` draws a QR code; `cmd+c` copies it as SVG",
            "`jwt \u003ctoken\u003e` shows the header, the payload and when it expires (the signature is not checked)",
            "`enter` copies, `cmd+enter` pastes into the app in front, `cmd+r` makes new values"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-everything.png",
              "caption": "The empty query: a fresh value of every generator, the secrets with their strength and entropy"
            },
            {
              "file": "2-hash.png",
              "caption": "hash of typed text: all four digests, and Copy all on cmd+shift+c"
            },
            {
              "file": "3-qr.png",
              "caption": "qr of a link: the code on the row and large in the detail pane"
            },
            {
              "file": "4-jwt.png",
              "caption": "jwt: the header, the payload with its expiry, the times, and a reminder that nothing is verified"
            },
            {
              "file": "5-password.png",
              "caption": "password 24: the password as the answer; the pane has its strength, length and entropy"
            }
          ],
          "actions": [
            {
              "title": "Copy",
              "description": "The value onto the clipboard.",
              "keys": "enter"
            },
            {
              "title": "Paste",
              "description": "Hides, then pastes the value into the app in front.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy all",
              "description": "Every row of the group (all hashes, all encodings, the JWT's header and payload) as lines.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Open in Colour Picker",
              "description": "A random colour in the Colors palette's picker.",
              "keys": "cmd+o"
            },
            {
              "title": "Show QR code",
              "description": "The code large, on the QR row.",
              "keys": "enter"
            },
            {
              "title": "Copy SVG",
              "description": "The QR code as SVG markup.",
              "keys": "cmd+c"
            }
          ]
        },
        "palettes": {
          "generate": {
            "title": "Generate",
            "kind": "input",
            "description": "Type nothing for a value of everything, a mode word to narrow it, or a mode and text to hash, encode, decode, draw or take apart.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the value (show the QR code on its row)"
              },
              {
                "keys": "cmd+enter",
                "title": "Paste the value into the app in front"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the whole group"
              },
              {
                "keys": "cmd+o",
                "title": "Open a colour in the Colour Picker"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the QR code as SVG"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/generate",
      "tagline": "UUIDs, passwords, hashes, base64, lorem ipsum, QR codes and JWTs",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/generate/screenshots/1-everything-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/1-everything.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/2-hash-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/2-hash.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/3-qr-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/3-qr.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/4-jwt-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/4-jwt.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/5-password-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/5-password.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/generate/screenshots/1-everything.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/2-hash.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/3-qr.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/4-jwt.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/5-password.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/generate/screenshots/1-everything-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/2-hash-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/3-qr-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/4-jwt-dark.png",
        "https://pal.cagdas.io/extensions/generate/screenshots/5-password-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "gifs",
      "kind": "registry",
      "title": "GIFs",
      "description": "Search Giphy and paste the GIF itself: Enter puts the file on the clipboard, so it lands as a picture in a chat or a document. Trending GIFs show before you type, and favourites keep in a grid of their own.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M2.666 0v24h18.668V8.666l-2.668 2.668v10H5.334V2.668H10L12.666 0zm10.668 0v8h8V5.334h-2.668V2.668H16V0",
          "box": 24,
          "bg": "#FF6666"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/gifs@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/gifs",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "gifs",
        "title": "GIFs",
        "description": "Search Giphy and paste the GIF itself: Enter puts the file on the clipboard, so it lands as a picture in a chat or a document. Trending GIFs show before you type, and favourites keep in a grid of their own.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M2.666 0v24h18.668V8.666l-2.668 2.668v10H5.334V2.668H10L12.666 0zm10.668 0v8h8V5.334h-2.668V2.668H16V0",
            "box": 24,
            "bg": "#FF6666"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "secret",
            "id": "giphy_api_key",
            "required": true,
            "label": "Giphy API key",
            "description": "From developers.giphy.com › Create an App (API, not SDK). Free, with a rate limit.",
            "placeholder": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "default": ""
          },
          {
            "kind": "select",
            "id": "content_filter",
            "label": "Content filter",
            "description": "Giphy's `rating`: what the results may show.",
            "options": [
              {
                "id": "off",
                "title": "Off (R)"
              },
              {
                "id": "low",
                "title": "Low (PG-13)"
              },
              {
                "id": "medium",
                "title": "Medium (PG)"
              },
              {
                "id": "high",
                "title": "High (G)"
              }
            ],
            "default": "medium"
          },
          {
            "kind": "path",
            "id": "save_to",
            "label": "Save to",
            "pick": "folder",
            "description": "Where cmd+s writes the GIF, named after its title.",
            "placeholder": "~/Downloads",
            "default": "~/Downloads"
          }
        ],
        "store": {
          "tagline": "Search Giphy and paste the GIF as a picture",
          "category": "fun",
          "features": [
            "A grid of animated previews from Giphy as you type; trending while nothing is typed",
            "`enter` puts the GIF file on the clipboard, so it pastes as a picture; `cmd+enter` copies the link",
            "`cmd+s` saves the GIF to Downloads, `cmd+o` opens its page on Giphy",
            "`cmd+f` keeps a GIF in Favourites, a grid of its own you can also search from the root",
            "Previews and GIFs you already fetched are cached, so a second look or copy is instant"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-trending.png",
              "caption": "Nothing typed: Giphy's trending GIFs as a grid"
            },
            {
              "file": "2-search.png",
              "caption": "Typing cat: the matches, and the detail pane with the preview, its size and its page"
            },
            {
              "file": "3-actions.png",
              "caption": "What a GIF can do: copy the file, copy the url, open, save, favourite"
            },
            {
              "file": "4-favourites.png",
              "caption": "Favourite GIFs: the ones cmd+f kept, and a tile to clear them"
            },
            {
              "file": "5-no-key.png",
              "caption": "Without a key: one tile saying so, the pane where to get one; Enter opens Settings"
            }
          ],
          "actions": [
            {
              "title": "Copy GIF",
              "description": "Downloads the GIF into the cache and puts the file on the clipboard.",
              "keys": "enter"
            },
            {
              "title": "Copy URL",
              "description": "The GIF file's url.",
              "keys": "cmd+enter"
            },
            {
              "title": "Open in browser",
              "description": "The GIF's page on giphy.com.",
              "keys": "cmd+o"
            },
            {
              "title": "Save to Downloads",
              "description": "The file written to `save_to`, named after its title.",
              "keys": "cmd+s"
            },
            {
              "title": "Add to favourites",
              "keys": "cmd+f"
            },
            {
              "title": "Remove from favourites",
              "description": "In the Favourites grid.",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "gifs": {
            "title": "GIFs",
            "kind": "grid",
            "fallback": "Search GIFs for “{query}”",
            "description": "Type to search; nothing typed lists what is trending. Every tile is an animated preview; Enter copies the GIF file.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the GIF file"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy the url"
              },
              {
                "keys": "cmd+o",
                "title": "Open the page"
              },
              {
                "keys": "cmd+s",
                "title": "Save to Downloads"
              },
              {
                "keys": "cmd+f",
                "title": "Add to favourites"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in both grids.",
                "min": 3,
                "max": 10,
                "default": 6
              }
            ]
          },
          "favourites": {
            "title": "Favourite GIFs",
            "kind": "grid",
            "description": "The GIFs kept with cmd+f, newest first; the same actions, and cmd+d removes one.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the GIF file"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy the url"
              },
              {
                "keys": "cmd+o",
                "title": "Open the page"
              },
              {
                "keys": "cmd+s",
                "title": "Save to Downloads"
              },
              {
                "keys": "cmd+d",
                "title": "Remove from favourites"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/gifs",
      "tagline": "Search Giphy and paste the GIF as a picture",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/gifs/screenshots/1-trending-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/1-trending.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/4-favourites-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/4-favourites.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/5-no-key-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/5-no-key.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/gifs/screenshots/1-trending.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/4-favourites.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/5-no-key.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/gifs/screenshots/1-trending-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/4-favourites-dark.png",
        "https://pal.cagdas.io/extensions/gifs/screenshots/5-no-key-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "github",
      "kind": "registry",
      "title": "GitHub",
      "description": "Your pull requests, issues, repositories and notifications, and a search over all of GitHub. Signs in through the gh CLI or a token.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12",
          "box": 24,
          "bg": "#181717"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/github@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/github",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "github",
        "title": "GitHub",
        "description": "Your pull requests, issues, repositories and notifications, and a search over all of GitHub. Signs in through the gh CLI or a token.",
        "keywords": [
          "gh"
        ],
        "version": "0.1.0",
        "multi": true,
        "icon": {
          "tile": {
            "svg": "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12",
            "box": 24,
            "bg": "#181717"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "secret",
            "id": "token",
            "label": "Token",
            "description": "A personal access token (repo, notifications, read:org). Leave empty to use the gh CLI's login.",
            "placeholder": "ghp_...",
            "default": ""
          },
          {
            "kind": "text",
            "id": "default_org",
            "label": "Organisation",
            "description": "An organisation whose recently pushed repositories are listed, and an owner the Create repository form offers.",
            "placeholder": "acme",
            "default": ""
          },
          {
            "kind": "path",
            "id": "repos_root",
            "label": "Clones folder",
            "pick": "folder",
            "description": "Where your clones live (\u003croot\u003e/\u003cname\u003e or \u003croot\u003e/\u003cowner\u003e/\u003cname\u003e): enables Checkout on a pull request and Open in editor on a repository.",
            "placeholder": "~/proj",
            "default": ""
          },
          {
            "kind": "select",
            "id": "clone_protocol",
            "label": "Clone URL",
            "description": "What Copy clone URL copies.",
            "options": [
              {
                "id": "ssh",
                "title": "SSH (git@github.com:...)"
              },
              {
                "id": "https",
                "title": "HTTPS"
              }
            ],
            "default": "ssh"
          },
          {
            "kind": "number",
            "id": "merged_days",
            "label": "Merged within",
            "description": "How far back the Merged list of Pull Requests reaches.",
            "min": 1,
            "max": 90,
            "unit": "days",
            "default": 7
          },
          {
            "kind": "select",
            "id": "merge_method",
            "label": "Merge method",
            "description": "How the Merge action merges.",
            "options": [
              {
                "id": "merge",
                "title": "Merge commit"
              },
              {
                "id": "squash",
                "title": "Squash"
              },
              {
                "id": "rebase",
                "title": "Rebase"
              }
            ],
            "default": "merge"
          }
        ],
        "palettes": {
          "prs": {
            "title": "Pull Requests",
            "description": "Yours, the ones waiting on your review, and what merged lately.",
            "ttl": 300,
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the pull request"
              },
              {
                "keys": "cmd+c",
                "title": "Copy its URL"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Checkout the branch"
              },
              {
                "keys": "cmd+b",
                "title": "Copy the branch name"
              },
              {
                "keys": "cmd+shift+k",
                "title": "Open the checks"
              },
              {
                "keys": "cmd+shift+f",
                "title": "Open the files changed"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Mark a draft ready for review"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Merge"
              },
              {
                "keys": "tab",
                "title": "All, Mine, Review requested, Merged"
              }
            ]
          },
          "issues": {
            "title": "Issues",
            "description": "Assigned to you, mentioning you, opened by you; Create issue.",
            "ttl": 300,
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the issue"
              },
              {
                "keys": "cmd+c",
                "title": "Copy its URL"
              },
              {
                "keys": "cmd+shift+x",
                "title": "Close it"
              },
              {
                "keys": "tab",
                "title": "All, Assigned, Mentioned, Created"
              }
            ]
          },
          "repos": {
            "title": "Repositories",
            "description": "Yours, starred, and your organisation's recently pushed.",
            "ttl": 300,
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open on GitHub"
              },
              {
                "keys": "cmd+e",
                "title": "Open the clone in the editor"
              },
              {
                "keys": "cmd+o",
                "title": "Open the clone's folder"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the clone URL"
              },
              {
                "keys": "cmd+p",
                "title": "Open the path typed in the bar"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the URL"
              },
              {
                "keys": "tab",
                "title": "All, Mine, Starred, Organisation"
              }
            ]
          },
          "notifications": {
            "title": "Notifications",
            "description": "Unread, by reason; opening one marks it read.",
            "ttl": 60,
            "kind": "live",
            "remember": false,
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Mark read and open"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Mark as read"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Mark all as read"
              },
              {
                "keys": "cmd+c",
                "title": "Copy its URL"
              }
            ]
          },
          "search": {
            "title": "Search GitHub",
            "description": "GitHub's search syntax over issues, pull requests, repositories and users, what you are involved in first.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Open what was found"
              },
              {
                "keys": "cmd+c",
                "title": "Copy its URL"
              },
              {
                "keys": "tab",
                "title": "Everything, Issues and PRs, Repositories, Users"
              }
            ]
          }
        },
        "bar": {
          "prs": {
            "title": "Pull requests",
            "description": "Separate PR status item over your own pull requests: red needs attention, amber is awaiting review or checks, green is ready to merge, muted is waiting; a review asked of you is a blue count only with `review_requests` on. The popover shows every bucket, reviews included, with the PR title, repo, state and age.",
            "mocks": {
              "attention": {
                "title": "Needs attention, with review requests on",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "blocked",
                      "text": "×2",
                      "color": "red"
                    },
                    {
                      "id": "waiting",
                      "text": "·1",
                      "color": "muted"
                    },
                    {
                      "id": "reviews",
                      "icon": "",
                      "text": "2",
                      "color": "blue"
                    }
                  ],
                  "tooltip": "5 open pull requests"
                }
              },
              "ready": {
                "title": "Ready to merge",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "ready",
                      "text": "✓1",
                      "color": "green"
                    }
                  ],
                  "tooltip": "1 open pull request"
                }
              },
              "active": {
                "title": "Awaiting review or checks",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "active",
                      "text": "…2",
                      "color": "amber"
                    }
                  ],
                  "tooltip": "2 open pull requests"
                }
              },
              "busy": {
                "title": "Every bucket at once",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "blocked",
                      "text": "×1",
                      "color": "red"
                    },
                    {
                      "id": "active",
                      "text": "…2",
                      "color": "amber"
                    },
                    {
                      "id": "ready",
                      "text": "✓1",
                      "color": "green"
                    },
                    {
                      "id": "waiting",
                      "text": "·3",
                      "color": "muted"
                    }
                  ],
                  "tooltip": "7 open pull requests"
                }
              },
              "clear": {
                "title": "No open pull requests",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "",
                    "tooltip": "No open pull requests"
                  }
                }
              }
            },
            "refresh": {
              "every": 300,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "settings": [
              {
                "kind": "boolean",
                "id": "review_requests",
                "label": "Review requests on the strip",
                "text": "Count the pull requests waiting on your review",
                "description": "Off (the default) keeps the Pull requests item to your own PRs, whose checks and reviews are yours to act on; a review asked of you is someone else's work and sits in the popover's own bucket either way.",
                "default": false
              }
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the focused pull request on GitHub"
              },
              {
                "keys": "c",
                "title": "Copy the focused pull request's URL"
              },
              {
                "keys": "m",
                "title": "Mute the focused pull request: out of the lists, the count and this popover until unmuted from the palette's Muted filter"
              },
              {
                "keys": "r",
                "title": "Refresh pull requests"
              },
              {
                "keys": "p",
                "title": "Open the Pull Requests palette"
              },
              {
                "keys": "up",
                "title": "Move between pull requests (or j and k)"
              }
            ]
          },
          "issues": {
            "title": "Issues",
            "description": "Separate Issues status item: assigned, mentioned, and your own open issues use distinct colours. The popover shows those buckets with the issue title, repo, labels, comments and age.",
            "mocks": {
              "assigned": {
                "title": "Assigned and mentioned",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "assigned",
                      "text": "@2",
                      "color": "blue"
                    },
                    {
                      "id": "mentioned",
                      "text": "@1",
                      "color": "amber"
                    }
                  ],
                  "tooltip": "3 open issues"
                }
              },
              "mine": {
                "title": "Your open issues",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "created",
                      "text": "·1",
                      "color": "muted"
                    }
                  ],
                  "tooltip": "1 open issue"
                }
              },
              "clear": {
                "title": "No open issues",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "",
                    "tooltip": "No open issues"
                  }
                }
              }
            },
            "refresh": {
              "every": 300,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the focused issue on GitHub"
              },
              {
                "keys": "c",
                "title": "Copy the focused issue's URL"
              },
              {
                "keys": "m",
                "title": "Mute the focused issue: out of the lists, the count and this popover until unmuted from the palette's Muted filter"
              },
              {
                "keys": "r",
                "title": "Refresh issues"
              },
              {
                "keys": "p",
                "title": "Open the Issues palette"
              },
              {
                "keys": "up",
                "title": "Move between issues (or j and k)"
              }
            ]
          },
          "notifications": {
            "title": "Notifications",
            "description": "The unread count as a badge, hidden at zero; the popover lists the unread threads by repository with their reason, opens or marks them read, marks all read.",
            "mocks": {
              "unread": {
                "title": "Unread notifications",
                "item": {
                  "icon": "",
                  "badge": 4,
                  "tooltip": "4 unread notifications"
                }
              },
              "one": {
                "title": "One notification",
                "item": {
                  "icon": "",
                  "badge": 1,
                  "tooltip": "1 unread notification"
                }
              },
              "clear": {
                "title": "All caught up",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "",
                    "tooltip": "No unread notifications"
                  }
                }
              }
            },
            "refresh": {
              "every": 300,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Mark the thread read and open it on GitHub"
              },
              {
                "keys": "m",
                "title": "Mark the thread read, or every marked thread (⌘-click, ⇧-click, ⇧↑↓)"
              },
              {
                "keys": "a",
                "title": "Mark all read"
              },
              {
                "keys": "p",
                "title": "Open the Notifications palette"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the thread's URL"
              },
              {
                "keys": "up",
                "title": "Move between threads (or j and k)"
              }
            ]
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Pull requests, issues, repos and notifications in the panel",
          "category": "developer",
          "features": [
            "Your pull requests, the ones waiting on your review and what merged this week, with checks and review state; mute one, or ignore it until it changes",
            "A pull request or issue in full: the body, latest comments and reviews, every check, who approved",
            "Your repositories, your organisation's and your stars; `cmd+e` opens the local clone in the editor",
            "Notifications by reason; `enter` opens the thread and marks it read, `space` in the popover reads it first",
            "Search all of GitHub as you type, your own work first; `is:pr`, `author:` and `label:` work as on GitHub",
            "Create an issue or a repository, check out a branch or merge, without leaving the keyboard"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-prs.png",
              "caption": "Pull Requests: Mine, Review requested and Merged, with the checks and the review decision on each row"
            },
            {
              "file": "2-pr-detail.png",
              "caption": "The pane a pull request opens with: the body, the latest comments and reviews, every check by name"
            },
            {
              "file": "3-notifications.png",
              "caption": "Notifications by reason, newest first; the first row is the unread count"
            },
            {
              "file": "4-search.png",
              "caption": "Search GitHub: repositories, issues, pull requests and users for one query"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the GitHub glyph with the unread count beside it",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the unread threads by repository with their reason and age; Enter opens one, m marks it read, a marks all read",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-work.png",
              "caption": "A second account, named Work, gets its own crumb; the arrows walk the threads and the footer names what Enter does",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                856
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the glyph with the unread count as its label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "The pull request, issue, repository, notification or profile on GitHub; a notification is marked read first.",
              "keys": "enter"
            },
            {
              "title": "Copy URL",
              "keys": "cmd+c"
            },
            {
              "title": "Checkout branch",
              "description": "gh pr checkout in the clone under repos_root.",
              "keys": "cmd+shift+o"
            },
            {
              "title": "Copy branch name",
              "keys": "cmd+b"
            },
            {
              "title": "Open checks",
              "keys": "cmd+shift+k"
            },
            {
              "title": "Open files changed",
              "keys": "cmd+shift+f"
            },
            {
              "title": "Copy reference",
              "description": "owner/repo#n."
            },
            {
              "title": "Mute / Unmute",
              "description": "Keeps an open pull request or issue out of the lists, the counts and the bar popovers; the Muted filter lists them to unmute.",
              "keys": "cmd+m"
            },
            {
              "title": "Mark ready for review",
              "description": "On a draft.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Merge",
              "description": "With merge_method; asks first.",
              "keys": "cmd+shift+m"
            },
            {
              "title": "Close issue",
              "description": "Asks first.",
              "keys": "cmd+shift+x"
            },
            {
              "title": "Create issue",
              "description": "A form: repository, title, body."
            },
            {
              "title": "Open in editor",
              "description": "The local clone, in code or the system opener.",
              "keys": "cmd+e"
            },
            {
              "title": "Open folder",
              "keys": "cmd+o"
            },
            {
              "title": "Copy clone URL",
              "description": "ssh or https, per clone_protocol.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy owner/name"
            },
            {
              "title": "Open issues"
            },
            {
              "title": "Open pull requests"
            },
            {
              "title": "Open path",
              "description": "The path typed in the bar (the repository row's argument) on the default branch; a form when picked without it.",
              "keys": "cmd+p"
            },
            {
              "title": "Create repository",
              "description": "A form: owner, name, description, private."
            },
            {
              "title": "Mark as read",
              "description": "Without opening.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Mark all as read",
              "description": "Asks first.",
              "keys": "cmd+shift+a"
            },
            {
              "title": "Open profile",
              "description": "A user found by Search.",
              "keys": "enter"
            },
            {
              "title": "Copy login",
              "keys": "cmd+c"
            },
            {
              "title": "Open repositories"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/github",
      "tagline": "Pull requests, issues, repos and notifications in the panel",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/github/screenshots/1-prs-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/1-prs.png",
        "https://pal.cagdas.io/extensions/github/screenshots/2-pr-detail-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/2-pr-detail.png",
        "https://pal.cagdas.io/extensions/github/screenshots/3-notifications-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/3-notifications.png",
        "https://pal.cagdas.io/extensions/github/screenshots/4-search-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/4-search.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover-work-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover-work.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/github/screenshots/1-prs.png",
        "https://pal.cagdas.io/extensions/github/screenshots/2-pr-detail.png",
        "https://pal.cagdas.io/extensions/github/screenshots/3-notifications.png",
        "https://pal.cagdas.io/extensions/github/screenshots/4-search.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/github/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover-work.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/github/screenshots/1-prs-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/2-pr-detail-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/3-notifications-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/4-search-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/github/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover-work-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/github/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "prs",
          "title": "Pull requests",
          "description": "Separate PR status item over your own pull requests: red needs attention, amber is awaiting review or checks, green is ready to merge, muted is waiting; a review asked of you is a blue count only with `review_requests` on. The popover shows every bucket, reviews included, with the PR title, repo, state and age.",
          "refresh": {
            "every": 300,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, when the panel shows, on wake, when the network is back"
        },
        {
          "id": "issues",
          "title": "Issues",
          "description": "Separate Issues status item: assigned, mentioned, and your own open issues use distinct colours. The popover shows those buckets with the issue title, repo, labels, comments and age.",
          "refresh": {
            "every": 300,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, when the panel shows, on wake, when the network is back"
        },
        {
          "id": "notifications",
          "title": "Notifications",
          "description": "The unread count as a badge, hidden at zero; the popover lists the unread threads by repository with their reason, opens or marks them read, marks all read.",
          "refresh": {
            "every": 300,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": true,
      "has_readme": true
    },
    {
      "name": "gmail",
      "kind": "registry",
      "title": "Gmail",
      "description": "Your Gmail inbox in the panel: read, search with Gmail's own syntax, browse labels and mark messages read, with the unread count on the bar. Each account is its own instance, and sending stays off until you turn it on.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M24 5.457v13.909c0 .904-.732 1.636-1.636 1.636h-3.819V11.73L12 16.64l-6.545-4.91v9.273H1.636A1.636 1.636 0 0 1 0 19.366V5.457c0-2.023 2.309-3.178 3.927-1.964L5.455 4.64 12 9.548l6.545-4.91 1.528-1.145C21.69 2.28 24 3.434 24 5.457z",
          "box": 24,
          "bg": "#EA4335"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/gmail@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/gmail",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "gmail",
        "title": "Gmail",
        "description": "Your Gmail inbox in the panel: read, search with Gmail's own syntax, browse labels and mark messages read, with the unread count on the bar. Each account is its own instance, and sending stays off until you turn it on.",
        "keywords": [
          "mail",
          "email"
        ],
        "version": "0.1.0",
        "multi": true,
        "icon": {
          "tile": {
            "svg": "M24 5.457v13.909c0 .904-.732 1.636-1.636 1.636h-3.819V11.73L12 16.64l-6.545-4.91v9.273H1.636A1.636 1.636 0 0 1 0 19.366V5.457c0-2.023 2.309-3.178 3.927-1.964L5.455 4.64 12 9.548l6.545-4.91 1.528-1.145C21.69 2.28 24 3.434 24 5.457z",
            "box": 24,
            "bg": "#EA4335"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "token_command",
            "scope": "instance",
            "label": "Token command",
            "description": "A shell command that prints an access token for the Gmail API: a bare token, or the JSON an OAuth endpoint answers (access_token, expires_in). The command owns the secret; pal keeps the token in memory until it expires and never writes it anywhere. gcloud auth application-default print-access-token, a helper, a broker behind ssh.",
            "placeholder": "gcloud auth application-default print-access-token",
            "default": ""
          },
          {
            "kind": "text",
            "id": "address",
            "scope": "instance",
            "label": "Address",
            "description": "The account's address, for the links into Gmail and the bar tooltip; read from the API when empty.",
            "placeholder": "you@gmail.com",
            "default": ""
          },
          {
            "kind": "list",
            "id": "labels",
            "label": "Labels",
            "description": "Labels whose unread mail the Inbox palette lists besides the inbox, one per line by name (a filter that skips the inbox, a list you follow).",
            "placeholder": "GitHub",
            "default": []
          },
          {
            "kind": "boolean",
            "id": "send",
            "scope": "instance",
            "label": "Send and change mail",
            "text": "Compose, reply, drafts, archive and star for this account",
            "description": "Off (the default) leaves the account read and mark-read only: no compose, no reply, no drafts, no archive, no star, whatever the token could do. Never inherited by another instance.",
            "default": false
          },
          {
            "kind": "text",
            "id": "signature",
            "label": "Signature",
            "description": "Appended under the body of a message composed or replied here, after a blank line.",
            "placeholder": "Cagdas",
            "default": ""
          }
        ],
        "palettes": {
          "inbox": {
            "title": "Inbox ({instance})",
            "description": "The inbox, unread first then recent, with the sender's avatar, the subject, the snippet, the labels, an attachment mark and the date; the pane is the message as text with the quoted replies folded.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "rank": 10,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the message in Gmail"
              },
              {
                "keys": "cmd+enter",
                "title": "Mark as read (Mark as unread on a read row)"
              },
              {
                "keys": "cmd+e",
                "title": "Archive (send on)"
              },
              {
                "keys": "cmd+s",
                "title": "Star or unstar (send on)"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Reply with the text typed in the bar (send on)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "search": {
            "title": "Search Mail ({instance})",
            "description": "Gmail's search as you type, its syntax passed through (from:, to:, subject:, has:attachment, newer_than:7d, label:), sectioned by label.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the message in Gmail"
              },
              {
                "keys": "cmd+enter",
                "title": "Mark as read (Mark as unread on a read row)"
              },
              {
                "keys": "cmd+e",
                "title": "Archive (send on)"
              },
              {
                "keys": "cmd+s",
                "title": "Star or unstar (send on)"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Reply with the text typed in the bar (send on)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "labels": {
            "title": "Labels ({instance})",
            "description": "Every label of the account, yours and Gmail's; a row opens the label in Gmail or searches it here.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "tier": "catalog",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the label in Gmail"
              },
              {
                "keys": "cmd+enter",
                "title": "Search the label here"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the label name"
              }
            ]
          },
          "compose": {
            "title": "Compose ({instance})",
            "description": "A new message as a form: to, cc, subject, body; the signature under it. Only with send on for the account.",
            "kind": "list",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the form; on the form, send"
              }
            ]
          },
          "drafts": {
            "title": "Drafts ({instance})",
            "description": "The drafts of the account with the recipient and the subject; open one in Gmail, send it, or discard it. Only with send on for the account.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the draft in Gmail"
              },
              {
                "keys": "cmd+enter",
                "title": "Send the draft, after a confirmation"
              },
              {
                "keys": "cmd+d",
                "title": "Discard the draft, after a confirmation"
              }
            ]
          }
        },
        "bar": {
          "unread": {
            "title": "Unread",
            "description": "The unread count of the inbox as a badge, hidden at zero, the account's title beside the glyph when it has one; the popover lists every unread as a row (the sender's mark, who wrote it, the subject and its snippet, the time, a star or a paperclip) with a cursor the arrows move and a click sets.",
            "refresh": {
              "every": 120,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "unread": {
                "title": "Unread mail",
                "item": {
                  "icon": "󰇮",
                  "badge": 3,
                  "tooltip": "3 unread messages in you@example.com"
                }
              },
              "one": {
                "title": "One unread message",
                "item": {
                  "icon": "󰇮",
                  "badge": 1,
                  "tooltip": "1 unread message in you@example.com"
                }
              },
              "named": {
                "title": "A named account",
                "item": {
                  "icon": "󰇮",
                  "title": "Work",
                  "badge": 7,
                  "tooltip": "7 unread messages in you@work.example"
                }
              },
              "clear": {
                "title": "Nothing unread",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰇮",
                    "tooltip": "No unread mail in you@example.com"
                  }
                }
              },
              "out": {
                "title": "Signed out",
                "item": {
                  "hidden": true
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the focused message in Gmail"
              },
              {
                "keys": "m",
                "title": "Mark the focused message read"
              },
              {
                "keys": "s",
                "title": "Star the focused message, or take its star off"
              },
              {
                "keys": "a",
                "title": "Mark every listed message read"
              },
              {
                "keys": "o",
                "title": "Open Gmail"
              },
              {
                "keys": "p",
                "title": "Open the Inbox palette in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy a link to the focused message"
              },
              {
                "keys": "up, down",
                "title": "Move between the rows; a click on a row focuses it"
              }
            ]
          }
        },
        "store": {
          "tagline": "Your inbox in the panel, its count on the bar, per account",
          "category": "integration",
          "features": [
            "The inbox, unread first: sender, subject, snippet, labels and attachments at a glance",
            "`enter` opens the thread in Gmail, `cmd+enter` marks it read; the side pane shows the message as text",
            "Search with Gmail's own syntax (`from:`, `has:attachment`, `newer_than:7d`) and browse every label",
            "An unread count on the bar, hidden at zero; its popover lists the unread messages, `space` reads one in full and `i` ignores a thread until someone writes in it again",
            "Several accounts side by side, each with its own tile badge, token and bar item",
            "Compose, reply, drafts, archive and star, only on accounts where you turn sending on"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-inbox.png",
              "caption": "Inbox: unread first, the sender, the subject and the snippet, a star or a paperclip, the time"
            },
            {
              "file": "2-detail.png",
              "caption": "The pane: the message as text with the quote folded, who and when, the labels, the attachment and its size"
            },
            {
              "file": "3-search.png",
              "caption": "Search Mail: Gmail's own syntax typed into the panel, the hits sectioned by label"
            },
            {
              "file": "4-labels.png",
              "caption": "Labels: yours and Gmail's, Enter opens one in Gmail, cmd+Enter searches it here"
            },
            {
              "file": "5-compose.png",
              "caption": "Compose: to, cc, subject and body, the signature already under it; only with send on"
            },
            {
              "file": "6-drafts.png",
              "caption": "Drafts: the recipient and the subject; send or discard, each after asking"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the envelope with the unread count, the account's title beside it",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: every unread message with the sender, subject and time, a star or a paperclip; m marks one read, a marks them all",
              "kind": "bar",
              "box": [
                378,
                64,
                840,
                796
              ]
            },
            {
              "file": "bar-popover-preview.png",
              "caption": "Space reads the message before deciding: the whole text, who and when, the attachment, with Enter, m and s still working there",
              "kind": "bar",
              "box": [
                378,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the envelope, the account's title and the count",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open in Gmail",
              "description": "The thread in the browser, in the account's own Gmail.",
              "keys": "enter"
            },
            {
              "title": "Mark as read",
              "description": "On an unread row; Mark as unread on a read one. Mark several rows (cmd-click, shift-click) to do them at once.",
              "keys": "cmd+enter"
            },
            {
              "title": "Archive",
              "description": "Out of the inbox; send on only.",
              "keys": "cmd+e"
            },
            {
              "title": "Star",
              "description": "Star or unstar; send on only.",
              "keys": "cmd+s"
            },
            {
              "title": "Reply",
              "description": "The text typed in the bar goes to the sender under the Re: subject, the original quoted under it; a form with to, cc, subject and body when picked without it; send on only.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Copy link",
              "keys": "cmd+c"
            },
            {
              "title": "Search label",
              "description": "On a label row: the search palette with label:\u003cname\u003e typed.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy name",
              "description": "On a label row.",
              "keys": "cmd+c"
            },
            {
              "title": "Compose",
              "description": "The form, then the message from the account.",
              "keys": "enter"
            },
            {
              "title": "Send draft",
              "description": "Asks first.",
              "keys": "cmd+enter"
            },
            {
              "title": "Discard draft",
              "description": "Asks first.",
              "keys": "cmd+d"
            },
            {
              "title": "Open Gmail settings",
              "description": "On a hint row: the extension's settings."
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/gmail",
      "tagline": "Your inbox in the panel, its count on the bar, per account",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/gmail/screenshots/1-inbox-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/1-inbox.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/4-labels-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/4-labels.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/5-compose-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/5-compose.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/6-drafts-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/6-drafts.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover-preview-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover-preview.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/gmail/screenshots/1-inbox.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/4-labels.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/5-compose.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/6-drafts.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover-preview.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/gmail/screenshots/1-inbox-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/4-labels-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/5-compose-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/6-drafts-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover-preview-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/gmail/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "unread",
          "title": "Unread",
          "description": "The unread count of the inbox as a badge, hidden at zero, the account's title beside the glyph when it has one; the popover lists every unread as a row (the sender's mark, who wrote it, the subject and its snippet, the time, a star or a paperclip) with a cursor the arrows move and a click sets.",
          "refresh": {
            "every": 120,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 2 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": true,
      "has_readme": true
    },
    {
      "name": "google",
      "kind": "registry",
      "title": "Google Search",
      "description": "Search Google from the panel with its suggestions as you type and a Wikipedia card for people, places and things. Add SerpApi, Brave Search or your own SearXNG to see answers and results right in the list.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
          "box": 24,
          "bg": "#4285F4"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/google@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/google",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "google",
        "title": "Google Search",
        "description": "Search Google from the panel with its suggestions as you type and a Wikipedia card for people, places and things. Add SerpApi, Brave Search or your own SearXNG to see answers and results right in the list.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
            "box": 24,
            "bg": "#4285F4"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "g",
          "web",
          "search"
        ],
        "settings": [
          {
            "kind": "select",
            "id": "provider",
            "label": "Results from",
            "description": "Where the web results come from. Suggestions come from Google with no key whatever this says; no free keyless service gives results reliably (DuckDuckGo, Bing's feed, Qwant, Mojeek and Startpage refuse or answer poorly without a browser).",
            "options": [
              {
                "id": "none",
                "title": "Nowhere (suggestions only)"
              },
              {
                "id": "serpapi",
                "title": "SerpApi (Google's own results)"
              },
              {
                "id": "brave",
                "title": "Brave Search API"
              },
              {
                "id": "searxng",
                "title": "A SearXNG instance"
              }
            ],
            "default": "none"
          },
          {
            "kind": "secret",
            "id": "serpapi_key",
            "required": true,
            "only": {
              "provider": "serpapi"
            },
            "label": "SerpApi key",
            "description": "From serpapi.com/manage-api-key. The free plan is 250 searches a month: with it, set Show results to When I ask. A query asked again within the hour is served from SerpApi's cache and costs nothing.",
            "placeholder": "a1b2…",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "brave_key",
            "required": true,
            "only": {
              "provider": "brave"
            },
            "label": "Brave Search API key",
            "description": "From api-dashboard.search.brave.com (the Search plan).",
            "placeholder": "BSA…",
            "default": ""
          },
          {
            "kind": "text",
            "id": "searxng_url",
            "required": true,
            "only": {
              "provider": "searxng"
            },
            "label": "SearXNG instance",
            "description": "Its address; `json` must be among the instance's search formats (settings.yml, search.formats).",
            "placeholder": "https://searx.example.org",
            "default": ""
          },
          {
            "kind": "select",
            "id": "results",
            "label": "Show results",
            "description": "As you type: the answer and the top five results join the list under the suggestions once you pause, and the pane previews a suggestion's (one request per query, cached). When I ask: only cmd+Enter searches.",
            "options": [
              {
                "id": "typing",
                "title": "As I type"
              },
              {
                "id": "ask",
                "title": "When I ask (cmd+Enter)"
              }
            ],
            "default": "typing"
          },
          {
            "kind": "select",
            "id": "language",
            "label": "Language",
            "description": "The language of the suggestions and results. Auto follows the system's.",
            "options": [
              {
                "id": "auto",
                "title": "Auto (the system's)"
              },
              {
                "id": "en",
                "title": "English"
              },
              {
                "id": "tr",
                "title": "Türkçe"
              },
              {
                "id": "de",
                "title": "Deutsch"
              },
              {
                "id": "fr",
                "title": "Français"
              },
              {
                "id": "es",
                "title": "Español"
              },
              {
                "id": "it",
                "title": "Italiano"
              },
              {
                "id": "nl",
                "title": "Nederlands"
              },
              {
                "id": "pt",
                "title": "Português"
              },
              {
                "id": "ru",
                "title": "Русский"
              },
              {
                "id": "ar",
                "title": "العربية"
              },
              {
                "id": "ja",
                "title": "日本語"
              },
              {
                "id": "zh-CN",
                "title": "中文"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "text",
            "id": "region",
            "label": "Region",
            "description": "A two-letter country code for what is local (tr, us, de); empty follows the system.",
            "placeholder": "tr",
            "default": ""
          },
          {
            "kind": "boolean",
            "id": "safe_search",
            "label": "Safe search",
            "text": "Filter explicit results",
            "default": false
          },
          {
            "kind": "select",
            "id": "browser",
            "label": "Open in",
            "description": "The browser a search or a result opens in.",
            "options": [
              {
                "id": "default",
                "title": "The default browser"
              },
              {
                "id": "Safari",
                "title": "Safari"
              },
              {
                "id": "Google Chrome",
                "title": "Google Chrome"
              },
              {
                "id": "Firefox",
                "title": "Firefox"
              },
              {
                "id": "Arc",
                "title": "Arc"
              },
              {
                "id": "Brave Browser",
                "title": "Brave"
              },
              {
                "id": "Microsoft Edge",
                "title": "Microsoft Edge"
              },
              {
                "id": "Chromium",
                "title": "Chromium"
              },
              {
                "id": "Vivaldi",
                "title": "Vivaldi"
              },
              {
                "id": "Zen",
                "title": "Zen"
              }
            ],
            "default": "default"
          },
          {
            "kind": "boolean",
            "id": "root",
            "label": "At the root",
            "text": "Suggestions under Search the web when nothing matches",
            "description": "Asked only when nothing on the machine matched what you typed, so a query pal answered itself is never sent to Google.",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "history",
            "label": "Recent searches",
            "text": "Remember searches and list them while nothing is typed",
            "default": true
          }
        ],
        "store": {
          "tagline": "Google suggestions, answers and results as you type",
          "category": "productivity",
          "features": [
            "Google's suggestions as you type, no key needed; `enter` searches, `tab` takes a suggestion",
            "A Wikipedia card in the side pane for a person, place or thing Google recognises",
            "With SerpApi, Brave Search or SearXNG: instant answers and top results under the suggestions",
            "`cmd+enter` lists every result as a row to open, open in the background or copy",
            "Offered at the root when nothing else matches; your query leaves the machine only then",
            "Recent searches before you type; language, region and safe search in Settings"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Search Google",
              "keys": "enter"
            },
            {
              "title": "Results here",
              "description": "The provider's answer and results as rows (with a provider set).",
              "keys": "cmd+enter"
            },
            {
              "title": "Search in the background",
              "keys": "cmd+b"
            },
            {
              "title": "Copy text",
              "keys": "cmd+c"
            },
            {
              "title": "Copy search link",
              "keys": "cmd+l"
            },
            {
              "title": "Complete",
              "description": "The suggestion into the search box.",
              "keys": "tab"
            },
            {
              "title": "Open in the background",
              "description": "On a result row.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy as Markdown link",
              "description": "On a result row.",
              "keys": "cmd+shift+c"
            }
          ],
          "screenshots": [
            {
              "file": "1-suggestions.png",
              "caption": "kadıköy typed: Google's suggestions, the district's Wikipedia card in the pane"
            },
            {
              "file": "2-preview.png",
              "caption": "With SerpApi: the answer and the top results join the list as you type, and the pane previews a suggestion's"
            },
            {
              "file": "3-results.png",
              "caption": "cmd+Enter: the answer and the results as rows, each with its site"
            },
            {
              "file": "4-actions.png",
              "caption": "What a result can do: open, open in the background, copy the link or a Markdown link"
            }
          ]
        },
        "palettes": {
          "google": {
            "title": "Google Search",
            "kind": "input",
            "description": "Type to get Google's suggestions; Enter searches, Tab completes, cmd+Enter lists the results here with a provider. Nothing typed lists recent searches.",
            "keys": [
              {
                "keys": "enter",
                "title": "Search Google (on a result: open it)"
              },
              {
                "keys": "tab",
                "title": "Put the suggestion in the box"
              },
              {
                "keys": "cmd+enter",
                "title": "Results here (on a result: open in the background)"
              },
              {
                "keys": "cmd+b",
                "title": "Search in the background"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the text (on a result: the link)"
              },
              {
                "keys": "cmd+l",
                "title": "Copy the search link"
              },
              {
                "keys": "ctrl+x",
                "title": "Remove a recent search"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/google",
      "tagline": "Google suggestions, answers and results as you type",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/google/screenshots/1-suggestions-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/1-suggestions.png",
        "https://pal.cagdas.io/extensions/google/screenshots/2-preview-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/2-preview.png",
        "https://pal.cagdas.io/extensions/google/screenshots/3-results-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/3-results.png",
        "https://pal.cagdas.io/extensions/google/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/4-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/google/screenshots/1-suggestions.png",
        "https://pal.cagdas.io/extensions/google/screenshots/2-preview.png",
        "https://pal.cagdas.io/extensions/google/screenshots/3-results.png",
        "https://pal.cagdas.io/extensions/google/screenshots/4-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/google/screenshots/1-suggestions-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/2-preview-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/3-results-dark.png",
        "https://pal.cagdas.io/extensions/google/screenshots/4-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "grafana",
      "kind": "registry",
      "title": "Grafana",
      "description": "Your Grafana dashboards, alerts and Prometheus queries from the panel, with a bar item that counts what is firing. Silence an alert for an hour or a day without opening the browser.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M23.02 10.59a8.578 8.578 0 0 0-.862-3.034 8.911 8.911 0 0 0-1.789-2.445c.337-1.342-.413-2.505-.413-2.505-1.292-.08-2.113.4-2.416.62-.052-.02-.102-.044-.154-.064-.22-.089-.446-.172-.677-.247-.231-.073-.47-.14-.711-.197a9.867 9.867 0 0 0-.875-.161C14.557.753 12.94 0 12.94 0c-1.804 1.145-2.147 2.744-2.147 2.744l-.018.093c-.098.029-.2.057-.298.088-.138.042-.275.094-.413.143-.138.055-.275.107-.41.166a8.869 8.869 0 0 0-1.557.87l-.063-.029c-2.497-.955-4.716.195-4.716.195-.203 2.658.996 4.33 1.235 4.636a11.608 11.608 0 0 0-.607 2.635C1.636 12.677.953 15.014.953 15.014c1.926 2.214 4.171 2.351 4.171 2.351.003-.002.006-.002.006-.005.285.509.615.994.986 1.446.156.19.32.371.488.548-.704 2.009.099 3.68.099 3.68 2.144.08 3.553-.937 3.849-1.173a9.784 9.784 0 0 0 3.164.501h.08l.055-.003.107-.002.103-.005.003.002c1.01 1.44 2.788 1.646 2.788 1.646 1.264-1.332 1.337-2.653 1.337-2.94v-.058c0-.02-.003-.039-.003-.06.265-.187.52-.387.758-.6a7.875 7.875 0 0 0 1.415-1.7c1.43.083 2.437-.885 2.437-.885-.236-1.49-1.085-2.216-1.264-2.354l-.018-.013-.016-.013a.217.217 0 0 1-.031-.02c.008-.092.016-.18.02-.27.011-.162.016-.323.016-.48v-.253l-.005-.098-.008-.135a1.891 1.891 0 0 0-.01-.13c-.003-.042-.008-.083-.013-.125l-.016-.124-.018-.122a6.215 6.215 0 0 0-2.032-3.73 6.015 6.015 0 0 0-3.222-1.46 6.292 6.292 0 0 0-.85-.048l-.107.002h-.063l-.044.003-.104.008a4.777 4.777 0 0 0-3.335 1.695c-.332.4-.592.84-.768 1.297a4.594 4.594 0 0 0-.312 1.817l.003.091c.005.055.007.11.013.164a3.615 3.615 0 0 0 .698 1.82 3.53 3.53 0 0 0 1.827 1.282c.33.098.66.14.971.137.039 0 .078 0 .114-.002l.063-.003c.02 0 .041-.003.062-.003.034-.002.065-.007.099-.01.007 0 .018-.003.028-.003l.031-.005.06-.008a1.18 1.18 0 0 0 .112-.02c.036-.008.072-.013.109-.024a2.634 2.634 0 0 0 .914-.415c.028-.02.056-.041.085-.065a.248.248 0 0 0 .039-.35.244.244 0 0 0-.309-.06l-.078.042c-.09.044-.184.083-.283.116a2.476 2.476 0 0 1-.475.096c-.028.003-.054.006-.083.006l-.083.002c-.026 0-.054 0-.08-.002l-.102-.006h-.012l-.024.006c-.016-.003-.031-.003-.044-.006-.031-.002-.06-.007-.091-.01a2.59 2.59 0 0 1-.724-.213 2.557 2.557 0 0 1-.667-.438 2.52 2.52 0 0 1-.805-1.475 2.306 2.306 0 0 1-.029-.444l.006-.122v-.023l.002-.031c.003-.021.003-.04.005-.06a3.163 3.163 0 0 1 1.352-2.29 3.12 3.12 0 0 1 .937-.43 2.946 2.946 0 0 1 .776-.101h.06l.07.002.045.003h.026l.07.005a4.041 4.041 0 0 1 1.635.49 3.94 3.94 0 0 1 1.602 1.662 3.77 3.77 0 0 1 .397 1.414l.005.076.003.075c.002.026.002.05.002.075 0 .024.003.052 0 .07v.065l-.002.073-.008.174a6.195 6.195 0 0 1-.08.639 5.1 5.1 0 0 1-.267.927 5.31 5.31 0 0 1-.624 1.13 5.052 5.052 0 0 1-3.237 2.014 4.82 4.82 0 0 1-.649.066l-.039.003h-.287a6.607 6.607 0 0 1-1.716-.265 6.776 6.776 0 0 1-3.4-2.274 6.75 6.75 0 0 1-.746-1.15 6.616 6.616 0 0 1-.714-2.596l-.005-.083-.002-.02v-.056l-.003-.073v-.096l-.003-.104v-.07l.003-.163c.008-.22.026-.45.054-.678a8.707 8.707 0 0 1 .28-1.355c.128-.444.286-.872.473-1.277a7.04 7.04 0 0 1 1.456-2.1 5.925 5.925 0 0 1 .953-.763c.169-.111.343-.213.524-.306.089-.05.182-.091.273-.135.047-.02.093-.042.138-.062a7.177 7.177 0 0 1 .714-.267l.145-.045c.049-.015.098-.026.148-.041.098-.029.197-.052.296-.076.049-.013.1-.02.15-.033l.15-.032.151-.028.076-.013.075-.01.153-.024c.057-.01.114-.013.171-.023l.169-.021c.036-.003.073-.008.106-.01l.073-.008.036-.003.042-.002c.057-.003.114-.008.171-.01l.086-.006h.023l.037-.003.145-.007a7.999 7.999 0 0 1 1.708.125 7.917 7.917 0 0 1 2.048.68 8.253 8.253 0 0 1 1.672 1.09l.09.077.089.078c.06.052.114.107.171.159.057.052.112.106.166.16.052.055.107.107.159.164a8.671 8.671 0 0 1 1.41 1.978c.012.026.028.052.04.078l.04.078.075.156c.023.051.05.1.07.153l.065.15a8.848 8.848 0 0 1 .45 1.34.19.19 0 0 0 .201.142.186.186 0 0 0 .172-.184c.01-.246.002-.532-.024-.856z",
          "box": 24,
          "bg": "#F46800"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/grafana@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/grafana",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "grafana",
        "title": "Grafana",
        "description": "Your Grafana dashboards, alerts and Prometheus queries from the panel, with a bar item that counts what is firing. Silence an alert for an hour or a day without opening the browser.",
        "version": "0.1.0",
        "multi": true,
        "icon": {
          "tile": {
            "svg": "M23.02 10.59a8.578 8.578 0 0 0-.862-3.034 8.911 8.911 0 0 0-1.789-2.445c.337-1.342-.413-2.505-.413-2.505-1.292-.08-2.113.4-2.416.62-.052-.02-.102-.044-.154-.064-.22-.089-.446-.172-.677-.247-.231-.073-.47-.14-.711-.197a9.867 9.867 0 0 0-.875-.161C14.557.753 12.94 0 12.94 0c-1.804 1.145-2.147 2.744-2.147 2.744l-.018.093c-.098.029-.2.057-.298.088-.138.042-.275.094-.413.143-.138.055-.275.107-.41.166a8.869 8.869 0 0 0-1.557.87l-.063-.029c-2.497-.955-4.716.195-4.716.195-.203 2.658.996 4.33 1.235 4.636a11.608 11.608 0 0 0-.607 2.635C1.636 12.677.953 15.014.953 15.014c1.926 2.214 4.171 2.351 4.171 2.351.003-.002.006-.002.006-.005.285.509.615.994.986 1.446.156.19.32.371.488.548-.704 2.009.099 3.68.099 3.68 2.144.08 3.553-.937 3.849-1.173a9.784 9.784 0 0 0 3.164.501h.08l.055-.003.107-.002.103-.005.003.002c1.01 1.44 2.788 1.646 2.788 1.646 1.264-1.332 1.337-2.653 1.337-2.94v-.058c0-.02-.003-.039-.003-.06.265-.187.52-.387.758-.6a7.875 7.875 0 0 0 1.415-1.7c1.43.083 2.437-.885 2.437-.885-.236-1.49-1.085-2.216-1.264-2.354l-.018-.013-.016-.013a.217.217 0 0 1-.031-.02c.008-.092.016-.18.02-.27.011-.162.016-.323.016-.48v-.253l-.005-.098-.008-.135a1.891 1.891 0 0 0-.01-.13c-.003-.042-.008-.083-.013-.125l-.016-.124-.018-.122a6.215 6.215 0 0 0-2.032-3.73 6.015 6.015 0 0 0-3.222-1.46 6.292 6.292 0 0 0-.85-.048l-.107.002h-.063l-.044.003-.104.008a4.777 4.777 0 0 0-3.335 1.695c-.332.4-.592.84-.768 1.297a4.594 4.594 0 0 0-.312 1.817l.003.091c.005.055.007.11.013.164a3.615 3.615 0 0 0 .698 1.82 3.53 3.53 0 0 0 1.827 1.282c.33.098.66.14.971.137.039 0 .078 0 .114-.002l.063-.003c.02 0 .041-.003.062-.003.034-.002.065-.007.099-.01.007 0 .018-.003.028-.003l.031-.005.06-.008a1.18 1.18 0 0 0 .112-.02c.036-.008.072-.013.109-.024a2.634 2.634 0 0 0 .914-.415c.028-.02.056-.041.085-.065a.248.248 0 0 0 .039-.35.244.244 0 0 0-.309-.06l-.078.042c-.09.044-.184.083-.283.116a2.476 2.476 0 0 1-.475.096c-.028.003-.054.006-.083.006l-.083.002c-.026 0-.054 0-.08-.002l-.102-.006h-.012l-.024.006c-.016-.003-.031-.003-.044-.006-.031-.002-.06-.007-.091-.01a2.59 2.59 0 0 1-.724-.213 2.557 2.557 0 0 1-.667-.438 2.52 2.52 0 0 1-.805-1.475 2.306 2.306 0 0 1-.029-.444l.006-.122v-.023l.002-.031c.003-.021.003-.04.005-.06a3.163 3.163 0 0 1 1.352-2.29 3.12 3.12 0 0 1 .937-.43 2.946 2.946 0 0 1 .776-.101h.06l.07.002.045.003h.026l.07.005a4.041 4.041 0 0 1 1.635.49 3.94 3.94 0 0 1 1.602 1.662 3.77 3.77 0 0 1 .397 1.414l.005.076.003.075c.002.026.002.05.002.075 0 .024.003.052 0 .07v.065l-.002.073-.008.174a6.195 6.195 0 0 1-.08.639 5.1 5.1 0 0 1-.267.927 5.31 5.31 0 0 1-.624 1.13 5.052 5.052 0 0 1-3.237 2.014 4.82 4.82 0 0 1-.649.066l-.039.003h-.287a6.607 6.607 0 0 1-1.716-.265 6.776 6.776 0 0 1-3.4-2.274 6.75 6.75 0 0 1-.746-1.15 6.616 6.616 0 0 1-.714-2.596l-.005-.083-.002-.02v-.056l-.003-.073v-.096l-.003-.104v-.07l.003-.163c.008-.22.026-.45.054-.678a8.707 8.707 0 0 1 .28-1.355c.128-.444.286-.872.473-1.277a7.04 7.04 0 0 1 1.456-2.1 5.925 5.925 0 0 1 .953-.763c.169-.111.343-.213.524-.306.089-.05.182-.091.273-.135.047-.02.093-.042.138-.062a7.177 7.177 0 0 1 .714-.267l.145-.045c.049-.015.098-.026.148-.041.098-.029.197-.052.296-.076.049-.013.1-.02.15-.033l.15-.032.151-.028.076-.013.075-.01.153-.024c.057-.01.114-.013.171-.023l.169-.021c.036-.003.073-.008.106-.01l.073-.008.036-.003.042-.002c.057-.003.114-.008.171-.01l.086-.006h.023l.037-.003.145-.007a7.999 7.999 0 0 1 1.708.125 7.917 7.917 0 0 1 2.048.68 8.253 8.253 0 0 1 1.672 1.09l.09.077.089.078c.06.052.114.107.171.159.057.052.112.106.166.16.052.055.107.107.159.164a8.671 8.671 0 0 1 1.41 1.978c.012.026.028.052.04.078l.04.078.075.156c.023.051.05.1.07.153l.065.15a8.848 8.848 0 0 1 .45 1.34.19.19 0 0 0 .201.142.186.186 0 0 0 .172-.184c.01-.246.002-.532-.024-.856z",
            "box": 24,
            "bg": "#F46800"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "grafana",
          "prometheus",
          "promql",
          "dashboards",
          "alerts",
          "metrics"
        ],
        "settings": [
          {
            "kind": "text",
            "id": "url",
            "required": true,
            "scope": "instance",
            "label": "URL",
            "placeholder": "https://grafana.example.com",
            "description": "Where Grafana answers, scheme included; no trailing slash needed.",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "token",
            "required": true,
            "label": "Token",
            "placeholder": "keychain:pal/grafana-token",
            "description": "A service account token (Administration › Service accounts): Viewer reads everything here, Editor is needed to silence alerts. Stored as a keychain: or env: reference.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "time_range",
            "label": "Time range",
            "placeholder": "now-6h",
            "description": "Appended to a dashboard's URL as from=…\u0026to=now when set (now-6h, now-24h, now-7d); leave empty to open the dashboard's own range.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "datasource",
            "label": "Prometheus datasource",
            "placeholder": "prometheus",
            "description": "The datasource the Query palette runs against, by uid or name; leave empty for Grafana's default.",
            "default": ""
          },
          {
            "kind": "list",
            "id": "queries",
            "label": "Saved queries",
            "placeholder": "Targets down = up == 0",
            "description": "PromQL listed before you type in the Query palette, one `Name = expr` per line (cmd+s on a result saves the one you ran).",
            "default": [
              "Targets down = up == 0",
              "Firing alerts = ALERTS{alertstate=\"firing\"}",
              "CPU busy % = 100 - avg by (instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100",
              "Memory used % = 100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)",
              "Root disk used % = 100 * (1 - node_filesystem_avail_bytes{mountpoint=\"/\"} / node_filesystem_size_bytes{mountpoint=\"/\"})"
            ]
          },
          {
            "kind": "number",
            "id": "sparklines",
            "label": "Panels in the pane",
            "description": "How many of a dashboard's time series panels the detail pane draws: as panel images when the image renderer plugin is installed, else as sparklines from the panels' queries. 0 turns it off.",
            "min": 0,
            "max": 6,
            "step": 1,
            "default": 3
          },
          {
            "kind": "number",
            "id": "timeout",
            "label": "Timeout",
            "description": "How long one request may take before the row says Grafana did not answer.",
            "min": 1,
            "max": 60,
            "step": 1,
            "unit": "s",
            "default": 8
          }
        ],
        "palettes": {
          "grafana": {
            "title": "Grafana Dashboards",
            "description": "Every dashboard, starred first, with its folder and tags; Enter opens it in the browser with the time range you set, cmd+enter asks for one. Folders as a filter that lists them, each a drill-in.",
            "kind": "list",
            "lazy": true,
            "ttl": 900,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the dashboard in the browser (with the `time_range` setting appended)"
              },
              {
                "keys": "cmd+enter",
                "title": "Open with a time range: from, to and kiosk asked in a form"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the URL"
              },
              {
                "keys": "cmd+s",
                "title": "Star or unstar (the token's own stars, which sort first here)"
              },
              {
                "keys": "cmd+f",
                "title": "Open in kiosk mode (no chrome, for a wall)"
              },
              {
                "keys": "cmd+u",
                "title": "Copy the uid"
              },
              {
                "keys": "right",
                "title": "The dashboard's folder as a level"
              },
              {
                "keys": "tab",
                "title": "All, Starred, Folders"
              }
            ]
          },
          "alerts": {
            "title": "Grafana Alerts",
            "description": "Every alert instance firing or pending, by rule, with its summary, severity, labels and since when; silences as a filter, with the active silences to expire.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 30,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the rule in Grafana"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the rule's dashboard"
              },
              {
                "keys": "cmd+s",
                "title": "Silence this instance for 1 hour (asks first)"
              },
              {
                "keys": "cmd+shift+s",
                "title": "Silence for 4 hours (asks first)"
              },
              {
                "keys": "cmd+d",
                "title": "Silence for 1 day (asks first)"
              },
              {
                "keys": "cmd+e",
                "title": "Expire the silence on a silenced instance, or a silence row (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the summary"
              },
              {
                "keys": "cmd+l",
                "title": "Copy the labels"
              },
              {
                "keys": "tab",
                "title": "All, Firing, Pending, Silenced"
              }
            ]
          },
          "query": {
            "title": "Grafana Query",
            "description": "A PromQL instant query against the Prometheus datasource, one row per series with its value; the saved queries before you type. Enter copies the value, cmd+o opens Explore.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the value (on a saved query: run it)"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy the series with its value"
              },
              {
                "keys": "cmd+o",
                "title": "Open the expression in Explore"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the expression"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Copy every series with its value"
              },
              {
                "keys": "cmd+s",
                "title": "Save the expression under a name (the `queries` setting)"
              },
              {
                "keys": "cmd+backspace",
                "title": "Remove a saved query"
              }
            ]
          }
        },
        "links": {
          "query": {
            "description": "Open the Query palette with an expression typed",
            "params": {
              "expr": {
                "description": "The PromQL",
                "required": true
              }
            }
          },
          "open": {
            "description": "Open a dashboard in the browser",
            "params": {
              "uid": {
                "description": "The dashboard's uid",
                "required": true
              },
              "from": {
                "description": "A time range start (now-6h, an ISO date); the `time_range` setting when absent"
              },
              "to": {
                "description": "Its end; now when absent"
              },
              "kiosk": {
                "description": "Kiosk mode",
                "type": "boolean"
              }
            }
          }
        },
        "states": {
          "firing": {
            "description": "Alert instances firing",
            "kind": "number"
          },
          "pending": {
            "description": "Alert instances pending (over the threshold, inside their `for`)",
            "kind": "number"
          }
        },
        "bar": {
          "alerts": {
            "title": "Alerts",
            "description": "How many alert instances are firing (red) and pending (amber); hidden while none is, by its rules. The popover lists them by state: Enter opens the rule, o the dashboard, s silences for an hour (f four, d a day), c copies the summary.",
            "refresh": {
              "every": 60,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "firing": {
                "title": "Two firing",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "firing",
                      "text": "2",
                      "color": "red"
                    }
                  ],
                  "tooltip": "2 firing on Grafana"
                }
              },
              "mixed": {
                "title": "One firing, one pending",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "firing",
                      "text": "1",
                      "color": "red"
                    },
                    {
                      "id": "pending",
                      "text": "1",
                      "color": "amber"
                    }
                  ],
                  "tooltip": "1 firing, 1 pending on Grafana"
                }
              },
              "pending": {
                "title": "One pending, nothing firing",
                "item": {
                  "icon": "",
                  "segments": [
                    {
                      "id": "pending",
                      "text": "1",
                      "color": "amber"
                    }
                  ],
                  "tooltip": "1 pending on Grafana"
                }
              },
              "quiet": {
                "title": "All quiet, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "",
                    "tooltip": "No alert is firing on Grafana"
                  }
                }
              }
            },
            "rules": [
              {
                "id": "quiet",
                "when": "not grafana.firing and not grafana.pending",
                "description": "Nothing firing or pending: nothing to say.",
                "hidden": true
              },
              {
                "id": "pending",
                "when": "grafana.pending and not grafana.firing",
                "description": "Something is over its threshold but inside its `for`.",
                "color": "amber"
              },
              {
                "id": "firing",
                "when": "grafana.firing",
                "description": "An alert is firing.",
                "color": "red"
              }
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the focused rule in Grafana"
              },
              {
                "keys": "o",
                "title": "Open its dashboard (the alert list without one)"
              },
              {
                "keys": "s",
                "title": "Silence the focused instance for 1 hour (asks first); on a silenced one, expire the silence"
              },
              {
                "keys": "f",
                "title": "Silence for 4 hours (asks first)"
              },
              {
                "keys": "d",
                "title": "Silence for 1 day (asks first)"
              },
              {
                "keys": "c",
                "title": "Copy the summary"
              },
              {
                "keys": "a",
                "title": "Open the alert list in Grafana"
              },
              {
                "keys": "p",
                "title": "Open Grafana Alerts in pal"
              },
              {
                "keys": "r",
                "title": "Refresh"
              },
              {
                "keys": "up",
                "title": "Move between alerts (or j and k)"
              }
            ]
          }
        },
        "store": {
          "tagline": "Dashboards, alerts and PromQL from the panel",
          "category": "developer",
          "features": [
            "Every dashboard by name, starred first, with its folder and tags; open it, pick a time range or go kiosk",
            "A preview of the dashboard's first graphs in the side pane",
            "Alerts firing and pending with summary, severity and labels; `cmd+s` silences one for an hour, `cmd+d` for a day",
            "A PromQL prompt: one row per series with its value, saved queries before you type, `cmd+o` opens Explore",
            "A bar item counting firing (red) and pending (amber) alerts, hidden while all is quiet",
            "Several Grafanas as separate instances; deep links open a query or a dashboard from a script"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-dashboards.png",
              "caption": "Every dashboard, starred first, its folder and tags on the right; the pane draws its first panels from their own queries"
            },
            {
              "file": "2-alerts.png",
              "caption": "What is firing and pending, by rule, with its severity and age; the pane leads with the rule, its state, value and how long, then the labels and the dashboard"
            },
            {
              "file": "3-silence.png",
              "caption": "Silence an instance for an hour, four or a day from the list, or jump to its dashboard"
            },
            {
              "file": "4-query.png",
              "caption": "A PromQL prompt: one row per series with its value; Enter copies it, ⌘O opens Explore"
            },
            {
              "file": "5-range.png",
              "caption": "⌘Enter asks for the range to open a dashboard over, and whether in kiosk mode for a wall"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the glyph red while something fires, then how many fire and how many are pending; hidden while all is quiet",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-pending.png",
              "caption": "Only pending: the count in amber, before an alert's wait is up",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the count leads, then firing and pending, each with its summary and age; s silences, o opens the dashboard",
              "kind": "bar",
              "box": [
                428,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the glyph and the two counts",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "The dashboard in the browser, with the `time_range` setting appended when set.",
              "keys": "enter"
            },
            {
              "title": "Open with a time range",
              "description": "From, to and kiosk asked in a form.",
              "keys": "cmd+enter"
            },
            {
              "title": "Star / Unstar",
              "keys": "cmd+s"
            },
            {
              "title": "Open in kiosk mode",
              "keys": "cmd+f"
            },
            {
              "title": "Copy URL",
              "keys": "cmd+c"
            },
            {
              "title": "Open rule",
              "description": "On an alert: the rule's page in Grafana.",
              "keys": "enter"
            },
            {
              "title": "Silence for 1 hour / 4 hours / 1 day",
              "description": "On an alert instance; asks first. Needs the Editor role.",
              "keys": "cmd+s"
            },
            {
              "title": "Expire silence",
              "description": "On a silenced instance or a silence row; asks first.",
              "keys": "cmd+e"
            },
            {
              "title": "Copy value",
              "description": "On a query result.",
              "keys": "enter"
            },
            {
              "title": "Open in Explore",
              "description": "On a query result or a saved query.",
              "keys": "cmd+o"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/grafana",
      "tagline": "Dashboards, alerts and PromQL from the panel",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/grafana/screenshots/1-dashboards-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/1-dashboards.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/2-alerts-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/2-alerts.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/3-silence-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/3-silence.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/4-query-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/4-query.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/5-range-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/5-range.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar-pending-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar-pending.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/grafana/screenshots/1-dashboards.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/2-alerts.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/3-silence.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/4-query.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/5-range.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar-pending.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/grafana/screenshots/1-dashboards-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/2-alerts-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/3-silence-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/4-query-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/5-range-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar-pending-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/grafana/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "alerts",
          "title": "Alerts",
          "description": "How many alert instances are firing (red) and pending (amber); hidden while none is, by its rules. The popover lists them by state: Enter opens the rule, o the dashboard, s silences for an hour (f four, d a day), c copies the summary.",
          "refresh": {
            "every": 60,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "query",
          "url": "pal://grafana/query?expr=\u003cexpr\u003e",
          "cli": "pal call grafana/query expr=\u003cexpr\u003e",
          "description": "Open the Query palette with an expression typed",
          "params": [
            {
              "name": "expr",
              "description": "The PromQL",
              "required": true
            }
          ]
        },
        {
          "route": "open",
          "url": "pal://grafana/open?uid=\u003cuid\u003e",
          "cli": "pal call grafana/open uid=\u003cuid\u003e",
          "description": "Open a dashboard in the browser",
          "params": [
            {
              "name": "uid",
              "description": "The dashboard's uid",
              "required": true
            },
            {
              "name": "from",
              "description": "A time range start (now-6h, an ISO date); the `time_range` setting when absent"
            },
            {
              "name": "to",
              "description": "Its end; now when absent"
            },
            {
              "name": "kiosk",
              "description": "Kiosk mode",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": true,
      "has_readme": true
    },
    {
      "name": "highway",
      "kind": "registry",
      "title": "Highway",
      "description": "Weave through highway traffic on a road trip across five regions: short Sprints on fixed roads with three stars each, a rival to beat at the end of every region for their car, and seventeen cars that open as you earn stars, each sharper than the last. Near misses chain into combos that carry you past your top speed. Free Drive has four endless modes with leaderboards, and Zen, where nothing ends the run.",
      "version": "1.0.0",
      "icon": {
        "tile": {
          "svg": "M1.5 15 6.6 1h1.1L4.6 15zM14.5 15 9.4 1H8.3l3.1 14zM7.45 12h1.1v2.6h-1.1zM7.55 7.2h.9v2.2h-.9zM7.65 3.4h.7v1.5h-.7z",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/highway@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/highway",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "highway",
        "title": "Highway",
        "description": "Weave through highway traffic on a road trip across five regions: short Sprints on fixed roads with three stars each, a rival to beat at the end of every region for their car, and seventeen cars that open as you earn stars, each sharper than the last. Near misses chain into combos that carry you past your top speed. Free Drive has four endless modes with leaderboards, and Zen, where nothing ends the run.",
        "version": "1.0.0",
        "icon": {
          "tile": {
            "svg": "M1.5 15 6.6 1h1.1L4.6 15zM14.5 15 9.4 1H8.3l3.1 14zM7.45 12h1.1v2.6h-1.1zM7.55 7.2h.9v2.2h-.9zM7.65 3.4h.7v1.5h-.7z",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "id": "volume",
            "label": "Volume",
            "kind": "number",
            "description": "How loud the game is: engine, traffic, music.",
            "min": 0,
            "max": 100,
            "step": 5,
            "unit": "%",
            "slider": true,
            "default": 80
          },
          {
            "kind": "select",
            "id": "resolution",
            "label": "Resolution",
            "description": "How many pixels the road is drawn with. Sharp is the crispest and takes about twice the power of Balanced, which warms a laptop; Battery is a little softer and takes a third of Sharp's.",
            "options": [
              {
                "id": "2",
                "title": "Sharp"
              },
              {
                "id": "1.5",
                "title": "Balanced"
              },
              {
                "id": "1.25",
                "title": "Battery"
              },
              {
                "id": "1",
                "title": "Lowest"
              }
            ],
            "default": "1.5"
          },
          {
            "id": "rush",
            "label": "Speed rush",
            "kind": "boolean",
            "text": "Past your top speed on a combo, the view widens, the road blurs and the wind roars",
            "default": true
          },
          {
            "id": "texts",
            "label": "Texts while driving",
            "kind": "boolean",
            "text": "A stop's text from the story lands in a corner halfway down the road, for a glance",
            "default": false
          },
          {
            "id": "ghost",
            "label": "Ghost",
            "kind": "boolean",
            "text": "Your best Sprint run drives beside you, faintly",
            "default": true
          }
        ],
        "sync": {
          "save": {
            "fields": {
              "v": "max",
              "paint": {
                "each": "latest"
              },
              "pick": "latest",
              "car": "latest",
              "location": "latest",
              "mode": "latest",
              "stop": "latest",
              "sprints": {
                "each": "min"
              },
              "best": {
                "fields": {
                  "endless": {
                    "fields": {
                      "score": "max",
                      "distance": "max",
                      "combo": "max",
                      "topSpeed": "max"
                    }
                  },
                  "twoway": {
                    "fields": {
                      "score": "max",
                      "distance": "max",
                      "combo": "max",
                      "topSpeed": "max"
                    }
                  },
                  "time": {
                    "fields": {
                      "score": "max",
                      "distance": "max",
                      "combo": "max",
                      "topSpeed": "max"
                    }
                  },
                  "trap": {
                    "fields": {
                      "score": "max",
                      "distance": "max",
                      "combo": "max",
                      "topSpeed": "max"
                    }
                  }
                }
              },
              "seen": "union",
              "totals": {
                "fields": {
                  "runs": "sum",
                  "distance": "sum",
                  "misses": "sum"
                }
              },
              "settings": {
                "fields": {
                  "view": "latest",
                  "music": "latest",
                  "sound": "latest",
                  "units": "latest"
                }
              }
            }
          },
          "run": "local",
          "scene": "local",
          "ghosts": "local",
          "tapes": "local"
        },
        "leaderboards": [
          {
            "id": "endless",
            "title": "Endless",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 100000000
          },
          {
            "id": "twoway",
            "title": "Two-Way",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 100000000
          },
          {
            "id": "time",
            "title": "Time Attack",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 100000000
          },
          {
            "id": "trap",
            "title": "Speed Trap",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 100000000
          },
          {
            "id": "stars",
            "title": "Road trip stars",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 150
          },
          {
            "id": "sprint/first-light",
            "title": "First Light (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/three-lanes",
            "title": "Three Lanes (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/commuters",
            "title": "Commuters (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/long-haul",
            "title": "Long Haul (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/farm-road",
            "title": "Farm Road (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/hedgerows",
            "title": "Hedgerows (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/squeeze",
            "title": "Squeeze (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/last-light",
            "title": "Last Light (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/heat-haze",
            "title": "Heat Haze (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/dry-run",
            "title": "Dry Run (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/old-road",
            "title": "The Old Road (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/noon-rush",
            "title": "Noon Rush (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/long-straight",
            "title": "Long Straight (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/white-lines",
            "title": "White Lines (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/overtaker",
            "title": "Overtaker (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/glare",
            "title": "Glare (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/big-block",
            "title": "Big Block (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/canyon-run",
            "title": "Canyon Run (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/head-on",
            "title": "Head-On (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/sundown",
            "title": "Sundown (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/the-mile",
            "title": "The Mile (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/low-sun",
            "title": "Low Sun (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/dust",
            "title": "Dust (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/rush-hour",
            "title": "Rush Hour (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/overcast",
            "title": "Overcast (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/drizzle",
            "title": "Drizzle (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/b-road",
            "title": "B-Road (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/motorway",
            "title": "Motorway (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/grand-tour",
            "title": "Grand Tour (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/convoy",
            "title": "Convoy (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/fog-line",
            "title": "Fog Line (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/slipstream",
            "title": "Slipstream (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/neon",
            "title": "Neon (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/midnight",
            "title": "Midnight (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/high-beams",
            "title": "High Beams (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/red-lights",
            "title": "Red Lights (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/all-night",
            "title": "All Night (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/tunnel-vision",
            "title": "Tunnel Vision (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/graveyard",
            "title": "Graveyard Shift (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/afterburn",
            "title": "Afterburn (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/duel-ines",
            "title": "Duel: Ines (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/duel-mika",
            "title": "Duel: Mika (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/duel-rook",
            "title": "Duel: Rook (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/duel-vega",
            "title": "Duel: Vega (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/legend-harvest",
            "title": "Legend: Harvest Rush (Countryside)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/legend-mirage",
            "title": "Legend: Mirage (High Noon)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/legend-red-sky",
            "title": "Legend: Red Sky (Golden Hour)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/legend-storm",
            "title": "Legend: The Storm (Grey Day)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/legend-long-night",
            "title": "Legend: The Long Night (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          },
          {
            "id": "sprint/duel-kaz",
            "title": "Duel: Kaz (Night Run)",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 900
          }
        ],
        "store": {
          "tagline": "A road trip through highway traffic",
          "category": "fun",
          "play": true,
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Drive",
              "description": "Up is the gas, down the brake, left and right steer; WASD too. That's the whole control.",
              "keys": "up, down, left, right"
            },
            {
              "title": "Change the view",
              "description": "Low behind the car, chase, the classic high angle, bumper, high, tower or long lens.",
              "keys": "c"
            },
            {
              "title": "Pause or carry on",
              "keys": "p"
            },
            {
              "title": "Sound on or off",
              "keys": "m"
            },
            {
              "title": "Try a Sprint again",
              "description": "From the run, the pause or the end of it.",
              "keys": "r"
            },
            {
              "title": "On the map",
              "description": "Left and right walk the road, up and down change region, Enter drives; G the garage, F Free Drive, Backspace back.",
              "keys": "enter"
            }
          ],
          "features": [
            "A road trip across five regions, from a quiet countryside morning to a night run, each with its own sky, its own car class and busier roads",
            "A story told in texts: Lina's parents are away, the house is empty, and she is 412 km off; her sister, her ex, the neighbour and her cousin are on the same road, and her dad's flight lands early",
            "Sprints: about a minute to a finish line on a road that is the same every try, so it can be learned; three stars for the time, your best run beside you as a ghost, R tries again at once",
            "A duel at the end of every region against a rival driving the best line; win it for their car and the next region",
            "A Legend in every region, its hardest road, open once you have three stars on its duel: finish it for a Legend paint every car can wear",
            "Handling built for feel: the car goes where your thumb says and stops where you let go, leaning and diving on its springs; every class turns in sharper, settles sooner and brakes harder",
            "Traffic with drivers: they keep their distance, brake, signal and change lanes when it's safe, placed so a lane is always open",
            "Near misses graded by the gap you left; near misses within four seconds build a combo, and a combo carries you past your top speed",
            "A garage of seventeen cars in five classes with their own engine notes: each duel wins you the next class's first, a region's stops finished open its others, and each new car gets a showcase; paint them any colour",
            "Free Drive: Endless, Two-Way, Time Attack and Speed Trap with any car you own, each with its leaderboard",
            "Signed in, your stars, cars and best times follow you to your other machines and play.cagdas.io"
          ],
          "screenshots": [
            {
              "file": "1-map.png",
              "caption": "The road trip: High Noon's stops on the map, each with its stars, the next one picked, the duel at the end of the road"
            },
            {
              "file": "2-run.png",
              "caption": "A Sprint in the Countryside: the clock, the road to the line and the time the next star needs, a combo carrying the Kiri past its top speed",
              "cover": [
                264,
                315,
                844,
                414
              ]
            },
            {
              "file": "3-garage.png",
              "caption": "The garage: your cars in their bays and the ones still under covers, each with what opens it"
            },
            {
              "file": "4-night.png",
              "caption": "Free Drive at night in the Saba: headlights on the road, tail lamps ahead, brake lights when a driver slows"
            },
            {
              "file": "5-results.png",
              "caption": "The end of a Free Drive run: the points and where they stand on the board"
            }
          ]
        },
        "palettes": {
          "highway": {
            "title": "Highway",
            "kind": "view",
            "description": "A run on the highway. Escape or closing the panel pauses it, and it waits there for you.",
            "keys": [
              {
                "keys": "up",
                "title": "Drive (arrows or WASD)"
              },
              {
                "keys": "c",
                "title": "Change the view"
              },
              {
                "keys": "p",
                "title": "Pause or carry on"
              },
              {
                "keys": "r",
                "title": "Try a Sprint again"
              },
              {
                "keys": "m",
                "title": "Sound on or off"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/highway",
      "tagline": "A road trip through highway traffic",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/highway/screenshots/1-map-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/1-map.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/2-run-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/2-run.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/3-garage-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/3-garage.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/4-night-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/4-night.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/5-results-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/5-results.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/highway/screenshots/1-map.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/2-run.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/3-garage.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/4-night.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/5-results.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/highway/screenshots/1-map-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/2-run-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/3-garage-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/4-night-dark.png",
        "https://pal.cagdas.io/extensions/highway/screenshots/5-results-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "home-assistant",
      "kind": "registry",
      "title": "Home Assistant",
      "description": "Your Home Assistant entities in the panel with their state: toggle lights, dim, set a temperature, lock a door, run a scene. Every service is a form, and areas list their own entities.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M22.939 10.627 13.061.749a1.505 1.505 0 0 0-2.121 0l-9.879 9.878C.478 11.21 0 12.363 0 13.187v9c0 .826.675 1.5 1.5 1.5h9.227l-4.063-4.062a2.034 2.034 0 0 1-.664.113c-1.13 0-2.05-.92-2.05-2.05s.92-2.05 2.05-2.05 2.05.92 2.05 2.05c0 .233-.041.456-.113.665l3.163 3.163V9.928a2.05 2.05 0 0 1-1.15-1.84c0-1.13.92-2.05 2.05-2.05s2.05.92 2.05 2.05a2.05 2.05 0 0 1-1.15 1.84v8.127l3.146-3.146A2.051 2.051 0 0 1 18 12.239c1.13 0 2.05.92 2.05 2.05s-.92 2.05-2.05 2.05c-.25 0-.488-.047-.709-.13L12.9 20.602v3.088h9.6c.825 0 1.5-.675 1.5-1.5v-9c0-.825-.477-1.977-1.061-2.561z",
          "box": 24,
          "bg": "#18BCF2"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/home-assistant@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/home-assistant",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "home-assistant",
        "title": "Home Assistant",
        "description": "Your Home Assistant entities in the panel with their state: toggle lights, dim, set a temperature, lock a door, run a scene. Every service is a form, and areas list their own entities.",
        "keywords": [
          "ha",
          "hass"
        ],
        "version": "0.1.0",
        "multi": true,
        "icon": {
          "tile": {
            "svg": "M22.939 10.627 13.061.749a1.505 1.505 0 0 0-2.121 0l-9.879 9.878C.478 11.21 0 12.363 0 13.187v9c0 .826.675 1.5 1.5 1.5h9.227l-4.063-4.062a2.034 2.034 0 0 1-.664.113c-1.13 0-2.05-.92-2.05-2.05s.92-2.05 2.05-2.05 2.05.92 2.05 2.05c0 .233-.041.456-.113.665l3.163 3.163V9.928a2.05 2.05 0 0 1-1.15-1.84c0-1.13.92-2.05 2.05-2.05s2.05.92 2.05 2.05a2.05 2.05 0 0 1-1.15 1.84v8.127l3.146-3.146A2.051 2.051 0 0 1 18 12.239c1.13 0 2.05.92 2.05 2.05s-.92 2.05-2.05 2.05c-.25 0-.488-.047-.709-.13L12.9 20.602v3.088h9.6c.825 0 1.5-.675 1.5-1.5v-9c0-.825-.477-1.977-1.061-2.561z",
            "box": 24,
            "bg": "#18BCF2"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "url",
            "required": true,
            "scope": "instance",
            "label": "URL",
            "placeholder": "http://homeassistant.local:8123",
            "description": "Where Home Assistant answers, scheme included; no trailing slash needed.",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "token",
            "required": true,
            "label": "Token",
            "placeholder": "keychain:pal/home-assistant-token",
            "description": "A long-lived access token (your profile in HA, Security, Long-lived access tokens). Stored as a keychain: or env: reference.",
            "default": ""
          },
          {
            "kind": "list",
            "id": "domains",
            "label": "Domains",
            "placeholder": "light",
            "description": "Entity domains listed at the root, in this order. A domain filter shows its domain regardless; favourites are listed regardless.",
            "default": [
              "light",
              "switch",
              "climate",
              "media_player",
              "cover",
              "lock",
              "fan",
              "scene",
              "script",
              "automation",
              "sensor",
              "binary_sensor",
              "person",
              "input_boolean"
            ]
          },
          {
            "kind": "list",
            "id": "favorites",
            "label": "Favourites",
            "placeholder": "light.kitchen",
            "description": "Entity ids pinned to the top, in this order.",
            "default": []
          },
          {
            "kind": "number",
            "id": "timeout",
            "label": "Timeout",
            "description": "How long one request may take before the row says Home Assistant did not answer.",
            "min": 1,
            "max": 60,
            "step": 1,
            "unit": "s",
            "default": 5
          }
        ],
        "store": {
          "tagline": "Toggle, dim and run Home Assistant entities from the panel",
          "category": "integration",
          "features": [
            "Every entity at the root with its state (`on`, `locked`, `playing`); favourites first, a filter per domain",
            "The right actions per kind: toggle and dim a light, set a thermostat, open a cover, lock a door, run a scene",
            "Brightness, temperature and volume typed straight into the search bar",
            "Every service as a form, its fields taken from Home Assistant",
            "Areas as lists of their entities; `cmd+o` opens an entity in Home Assistant",
            "A hotkey on any entity toggles it without showing the panel"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-entities.png",
              "caption": "Every entity with its state as a tag and when it last changed, the favourites leading; Enter toggles the light under the cursor"
            },
            {
              "file": "2-actions.png",
              "caption": "What a light can do: toggle, on, off, set brightness, and the rows every entity has"
            },
            {
              "file": "3-detail.png",
              "caption": "Show attributes (cmd+shift+A): the thermostat's state and every attribute as a row, Enter copies the value"
            },
            {
              "file": "4-service.png",
              "caption": "A service as a form: the target entity, then the fields Home Assistant describes for it, called with Enter"
            },
            {
              "file": "5-entity.png",
              "caption": "An entity in the detail pane (cmd+I): where it lives, its state as a chip, the reading and the target large, then its attributes"
            }
          ],
          "actions": [
            {
              "title": "Toggle",
              "description": "Lights, switches, fans, input booleans.",
              "keys": "enter"
            },
            {
              "title": "Turn on / Turn off",
              "keys": "cmd+enter"
            },
            {
              "title": "Set brightness",
              "description": "A light: the percent typed in the bar, light.turn_on with brightness_pct.",
              "keys": "cmd+b"
            },
            {
              "title": "Set temperature",
              "description": "The bar takes a thermostat's temperature (the current one prefilled, its range as the hint) and mode, then climate.set_temperature.",
              "keys": "enter"
            },
            {
              "title": "Open / Close / Stop",
              "description": "Covers."
            },
            {
              "title": "Lock / Unlock",
              "description": "Both ask first."
            },
            {
              "title": "Play / Pause, Next track, Previous track, Turn off",
              "description": "Media players."
            },
            {
              "title": "Set volume",
              "description": "A media player: the percent typed in the bar, media_player.volume_set.",
              "keys": "cmd+u"
            },
            {
              "title": "Activate / Run / Trigger",
              "description": "Scenes, scripts, automations; Enable or Disable for an automation."
            },
            {
              "title": "Press",
              "description": "Buttons."
            },
            {
              "title": "Start / Return to dock",
              "description": "Vacuums."
            },
            {
              "title": "Copy value",
              "description": "Sensors, people and every other domain.",
              "keys": "enter"
            },
            {
              "title": "Copy entity id",
              "keys": "cmd+c"
            },
            {
              "title": "Show attributes",
              "description": "A level with the state and every attribute; each row copies its value.",
              "keys": "cmd+shift+a"
            },
            {
              "title": "Open in Home Assistant",
              "description": "The automation or script editor, the history page for the rest.",
              "keys": "cmd+o"
            },
            {
              "title": "Call",
              "description": "On a service: the form, then the call.",
              "keys": "enter"
            },
            {
              "title": "Copy service id",
              "keys": "cmd+c"
            },
            {
              "title": "Show entities",
              "description": "On an area.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "entities": {
            "title": "Home Assistant",
            "kind": "live",
            "lazy": true,
            "description": "Every entity of the chosen domains with its state, favourites first; the domain filters scope it. Actions per domain: toggle, on, off, brightness, temperature, open, close, lock, play, activate, run, trigger, copy value; every row copies its id, shows its attributes, opens in HA.",
            "keys": [
              {
                "keys": "enter",
                "title": "The domain's first action: toggle, activate, run, copy value"
              },
              {
                "keys": "cmd+enter",
                "title": "The second: turn on or off, set, pause"
              },
              {
                "keys": "cmd+b",
                "title": "Set a light's brightness to the percent typed in the bar"
              },
              {
                "keys": "cmd+u",
                "title": "Set a media player's volume to the percent typed in the bar"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the entity id"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Show the attributes"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Home Assistant"
              },
              {
                "keys": "tab",
                "title": "All entities, Every domain, one domain"
              }
            ]
          },
          "services": {
            "title": "Home Assistant Services",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "description": "Every service Home Assistant offers, by domain; Enter opens a form with the target entity and the service's fields, submit calls it.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the form, then call"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the service id"
              }
            ]
          },
          "areas": {
            "title": "Home Assistant Areas",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "description": "Every area with an entity in it; Enter lists those entities.",
            "keys": [
              {
                "keys": "enter",
                "title": "List the area's entities"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/home-assistant",
      "tagline": "Toggle, dim and run Home Assistant entities from the panel",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/1-entities-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/1-entities.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/3-detail-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/3-detail.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/4-service-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/4-service.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/5-entity-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/5-entity.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/1-entities.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/3-detail.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/4-service.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/5-entity.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/1-entities-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/3-detail-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/4-service-dark.png",
        "https://pal.cagdas.io/extensions/home-assistant/screenshots/5-entity-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": true,
      "has_readme": true
    },
    {
      "name": "hue",
      "kind": "registry",
      "title": "Hue",
      "description": "Your Philips Hue lights, rooms and scenes under the keys, kept live as they change. Set colour, brightness and warmth, check sensors, and see the home at a glance from the menu bar.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M20.672 9.6c-2.043 0-3.505 1.386-3.682 3.416h-.664c-.247 0-.395.144-.395.384 0 .24.148.384.395.384h.661c.152 2.09 1.652 3.423 3.915 3.423.944 0 1.685-.144 2.332-.453.158-.075.337-.217.292-.471a.334.334 0 0 0-.15-.242c-.104-.065-.25-.072-.422-.02a7.93 7.93 0 0 0-.352.12c-.414.146-.771.273-1.599.273-1.75 0-2.908-1.023-2.952-2.605v-.025h5.444c.313 0 .492-.164.505-.463v-.058C23.994 9.865 21.452 9.6 20.672 9.6zm2.376 3.416h-5l.004-.035c.121-1.58 1.161-2.601 2.649-2.601 1.134 0 2.347.685 2.347 2.606zM9.542 10.221c0-.335-.195-.534-.52-.534s-.52.2-.52.534v2.795h1.04zm4.29 3.817c0 1.324-.948 2.361-2.16 2.361-1.433 0-2.13-.763-2.13-2.333v-.282h-1.04v.34c0 2.046.965 3.083 2.868 3.083 1.12 0 1.943-.486 2.443-1.445l.02-.036v.861c0 .334.193.534.519.534.325 0 .52-.2.52-.534v-2.803h-1.04zm.52-4.351c-.326 0-.52.2-.52.534v2.795h1.04v-2.795c0-.335-.195-.534-.52-.534zM3.645 9.6c-1.66 0-2.31 1.072-2.471 1.4l-.135.278V7.355c0-.347-.199-.562-.52-.562-.32 0-.519.215-.519.562v5.661h1.039v-.015c0-1.249.72-2.592 2.304-2.592 1.29 0 2.001.828 2.001 2.332v.275h1.04v-.246c0-2.044-.973-3.17-2.739-3.17zM0 16.558c0 .347.199.563.52.563.32 0 .519-.216.519-.563v-2.774H0zm5.344 0c0 .347.2.563.52.563s.52-.216.52-.563v-2.774h-1.04z",
          "box": 24,
          "bg": "#0065D3"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/hue@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/hue",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "hue",
        "title": "Hue",
        "description": "Your Philips Hue lights, rooms and scenes under the keys, kept live as they change. Set colour, brightness and warmth, check sensors, and see the home at a glance from the menu bar.",
        "keywords": [
          "lights"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M20.672 9.6c-2.043 0-3.505 1.386-3.682 3.416h-.664c-.247 0-.395.144-.395.384 0 .24.148.384.395.384h.661c.152 2.09 1.652 3.423 3.915 3.423.944 0 1.685-.144 2.332-.453.158-.075.337-.217.292-.471a.334.334 0 0 0-.15-.242c-.104-.065-.25-.072-.422-.02a7.93 7.93 0 0 0-.352.12c-.414.146-.771.273-1.599.273-1.75 0-2.908-1.023-2.952-2.605v-.025h5.444c.313 0 .492-.164.505-.463v-.058C23.994 9.865 21.452 9.6 20.672 9.6zm2.376 3.416h-5l.004-.035c.121-1.58 1.161-2.601 2.649-2.601 1.134 0 2.347.685 2.347 2.606zM9.542 10.221c0-.335-.195-.534-.52-.534s-.52.2-.52.534v2.795h1.04zm4.29 3.817c0 1.324-.948 2.361-2.16 2.361-1.433 0-2.13-.763-2.13-2.333v-.282h-1.04v.34c0 2.046.965 3.083 2.868 3.083 1.12 0 1.943-.486 2.443-1.445l.02-.036v.861c0 .334.193.534.519.534.325 0 .52-.2.52-.534v-2.803h-1.04zm.52-4.351c-.326 0-.52.2-.52.534v2.795h1.04v-2.795c0-.335-.195-.534-.52-.534zM3.645 9.6c-1.66 0-2.31 1.072-2.471 1.4l-.135.278V7.355c0-.347-.199-.562-.52-.562-.32 0-.519.215-.519.562v5.661h1.039v-.015c0-1.249.72-2.592 2.304-2.592 1.29 0 2.001.828 2.001 2.332v.275h1.04v-.246c0-2.044-.973-3.17-2.739-3.17zM0 16.558c0 .347.199.563.52.563.32 0 .519-.216.519-.563v-2.774H0zm5.344 0c0 .347.2.563.52.563s.52-.216.52-.563v-2.774h-1.04z",
            "box": 24,
            "bg": "#0065D3"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "bridge",
            "label": "Bridge",
            "placeholder": "192.168.1.25",
            "description": "The bridge's address, for a key kept in the keychain (below). Pairing from Set up Hue needs neither: it finds the bridge and keeps the key in pal's storage.",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "application_key",
            "label": "Application key",
            "placeholder": "keychain:pal/hue-application_key",
            "description": "The hue-application-key for the bridge above, as a keychain: or env: reference. Set up Hue shows the key it made (c copies it); pasting it here moves it into the keychain.",
            "default": ""
          },
          {
            "kind": "boolean",
            "id": "insecure",
            "label": "Certificate",
            "text": "Skip the bridge's certificate check",
            "description": "Off, every request is verified against Signify's root CA plus the certificate pinned at pairing. On for a bridge behind a proxy or a very old firmware whose certificate fails that.",
            "default": false
          },
          {
            "kind": "number",
            "id": "transition",
            "label": "Transition",
            "description": "How long a change from a row or a link takes on the lights; the view has its own, cycled with d.",
            "min": 0,
            "max": 10000,
            "step": 100,
            "unit": "ms",
            "default": 400
          },
          {
            "kind": "number",
            "id": "timeout",
            "label": "Timeout",
            "description": "How long one request to the bridge may take before the row says it did not answer.",
            "min": 1,
            "max": 30,
            "step": 1,
            "unit": "s",
            "default": 5
          }
        ],
        "store": {
          "tagline": "Every Hue light, room and scene, live, under the keys",
          "category": "integration",
          "features": [
            "Rooms and scenes at the root: type `living room` to toggle it, `relax` to play the scene",
            "A light or room in full: brightness on the arrows, warmth, colour, presets, scenes and effects",
            "Live: changes made in the Hue app or on a switch show up at once",
            "Sensors with their last reading and battery; automations and entertainment areas on or off",
            "A bar item with the lights that are on; its popover toggles rooms and plays scenes",
            "Guided setup finds the bridge and waits for its button; several bridges act as one home"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-rooms.png",
              "caption": "Rooms and zones with their colour, how many lights are on and the brightness; Enter toggles, cmd+Enter opens the room"
            },
            {
              "file": "2-light.png",
              "caption": "A light under the keys: the tile in its colour, brightness, the temperature strip, the colour plane, presets, scenes and effects"
            },
            {
              "file": "3-room.png",
              "caption": "A room under the keys, its scenes row focused: the arrows choose, Enter plays"
            },
            {
              "file": "4-scenes.png",
              "caption": "Scenes by room as five-swatch strips, the active and dynamic ones tagged"
            },
            {
              "file": "5-sensors.png",
              "caption": "Sensors and switches by device: motion, temperature, light level, the last button press, batteries"
            },
            {
              "file": "6-setup.png",
              "caption": "Set up Hue waiting for the button, with the countdown"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the bulb and how many lights are on",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the rooms as tiles in their colour (the switch toggles, the chevron opens), the motion and temperature, the main room's scenes, the keys",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                830
              ]
            },
            {
              "file": "bar-popover-room.png",
              "caption": "The living room opened: its lights inline, each with a brightness slider and a switch; the arrows walk them",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the bulb and the count on the label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Toggle",
              "description": "A room, zone or light.",
              "keys": "enter"
            },
            {
              "title": "Open room / Open light",
              "description": "The view under the keys.",
              "keys": "cmd+enter"
            },
            {
              "title": "Turn on / Turn off"
            },
            {
              "title": "Set brightness or temperature",
              "description": "The bar's fields on a room or light row: a brightness in % (0 is off) and, where the light tunes white, a colour temperature in K; one PUT with the transition.",
              "keys": "cmd+shift+b"
            },
            {
              "title": "Scenes of the room",
              "keys": "cmd+s"
            },
            {
              "title": "Lights in the room",
              "keys": "cmd+l"
            },
            {
              "title": "Blink to find it",
              "description": "A light breathes once.",
              "keys": "cmd+b"
            },
            {
              "title": "Copy colour",
              "description": "The light's colour as hex.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy id",
              "description": "For item_hotkeys and links.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Activate",
              "description": "A scene.",
              "keys": "enter"
            },
            {
              "title": "Play dynamically",
              "description": "A scene with a palette.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy value",
              "description": "A sensor's reading.",
              "keys": "enter"
            },
            {
              "title": "Enable or disable",
              "description": "A sensor or an automation.",
              "keys": "cmd+e"
            },
            {
              "title": "Start streaming / Stop streaming",
              "description": "An entertainment area.",
              "keys": "enter"
            },
            {
              "title": "Set up Hue",
              "description": "Find a bridge, press its button, pair."
            }
          ]
        },
        "palettes": {
          "rooms": {
            "title": "Hue Rooms",
            "kind": "live",
            "lazy": true,
            "tier": "primary",
            "description": "Every room and zone with its colour as a tile, how many of its lights are on and the brightness. Enter toggles it, cmd+Enter opens it under the keys.",
            "keys": [
              {
                "keys": "enter",
                "title": "Toggle the room"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the room under the keys"
              },
              {
                "keys": "cmd+shift+b",
                "title": "Set the brightness (%) and colour temperature (K) typed in the bar"
              },
              {
                "keys": "cmd+s",
                "title": "The room's scenes"
              },
              {
                "keys": "cmd+l",
                "title": "The room's lights"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the id"
              }
            ]
          },
          "lights": {
            "title": "Hue Lights",
            "kind": "live",
            "lazy": true,
            "description": "Every light by room with its colour as a swatch, its brightness and temperature, and whether the bridge can reach it. Enter toggles, cmd+Enter opens it under the keys.",
            "keys": [
              {
                "keys": "enter",
                "title": "Toggle the light"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the light under the keys"
              },
              {
                "keys": "cmd+shift+b",
                "title": "Set the brightness (%) and colour temperature (K) typed in the bar"
              },
              {
                "keys": "cmd+b",
                "title": "Blink it"
              },
              {
                "keys": "cmd+c",
                "title": "Copy its colour"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the id"
              }
            ]
          },
          "scenes": {
            "title": "Hue Scenes",
            "kind": "live",
            "lazy": true,
            "tier": "primary",
            "description": "Every scene by room as a five-swatch strip of its palette, the active one tagged; smart scenes too. Enter plays it, cmd+Enter plays it dynamically.",
            "keys": [
              {
                "keys": "enter",
                "title": "Play the scene"
              },
              {
                "keys": "cmd+enter",
                "title": "Play it dynamically"
              },
              {
                "keys": "cmd+o",
                "title": "Open the room under the keys"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the id"
              }
            ]
          },
          "light": {
            "title": "Hue Light",
            "kind": "view",
            "description": "A light or a room under the keys: the tile in its colour, brightness on the arrows and digits, colour temperature and colour on strips, presets, the room's scenes, effects, the scope and the transition.",
            "keys": [
              {
                "keys": "left, right",
                "title": "Brightness (shift: big steps); hue on the colour row; choose on the other rows"
              },
              {
                "keys": "up, down",
                "title": "Cooler or warmer; saturation on the colour row; the row above or below elsewhere"
              },
              {
                "keys": "1-9, 0",
                "title": "10% to 90%, off"
              },
              {
                "keys": "tab, shift+tab",
                "title": "Light, colour, presets, scenes, effects"
              },
              {
                "keys": "enter",
                "title": "Toggle, or apply the chosen preset, scene or effect"
              },
              {
                "keys": "t, space",
                "title": "Toggle"
              },
              {
                "keys": "a",
                "title": "Apply to this light or the whole room"
              },
              {
                "keys": "d",
                "title": "Transition: instant, 400 ms, 1 s, 4 s"
              },
              {
                "keys": "s",
                "title": "The room's scenes as a list"
              },
              {
                "keys": "o",
                "title": "Open the room"
              },
              {
                "keys": "i",
                "title": "Blink the light"
              },
              {
                "keys": "c",
                "title": "Copy the colour"
              },
              {
                "keys": "r",
                "title": "Read the bridge again"
              }
            ]
          },
          "setup": {
            "title": "Set up Hue",
            "kind": "view",
            "description": "Pairing: the bridges found on the network, press-link with a countdown, the key kept and the certificate pinned.",
            "keys": [
              {
                "keys": "1-9, enter",
                "title": "Pair with a bridge"
              },
              {
                "keys": "i",
                "title": "Type an address"
              },
              {
                "keys": "r",
                "title": "Scan again"
              },
              {
                "keys": "x",
                "title": "Forget a bridge, or stop a pairing"
              },
              {
                "keys": "b",
                "title": "Back to the bridges"
              },
              {
                "keys": "c",
                "title": "Copy the key once paired"
              }
            ]
          },
          "sensors": {
            "title": "Hue Sensors",
            "kind": "live",
            "lazy": true,
            "description": "Motion, temperature, light level, buttons and dials with their last event, contact sensors, and each device's battery. Enter copies the reading, cmd+e enables or disables the sensor.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the reading"
              },
              {
                "keys": "cmd+e",
                "title": "Enable or disable"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the id"
              }
            ]
          },
          "automations": {
            "title": "Hue Automations",
            "kind": "live",
            "lazy": true,
            "description": "The bridge's automations (wake up, go to sleep, timers, motion) with their status. Enter enables or disables one.",
            "keys": [
              {
                "keys": "enter",
                "title": "Enable or disable"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the id"
              }
            ]
          },
          "entertainment": {
            "title": "Hue Entertainment",
            "kind": "live",
            "lazy": true,
            "description": "Entertainment areas with their type and lights; Enter starts streaming, cmd+Enter stops it.",
            "keys": [
              {
                "keys": "enter",
                "title": "Start streaming"
              },
              {
                "keys": "cmd+enter",
                "title": "Stop streaming"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the id"
              }
            ]
          }
        },
        "bar": {
          "home": {
            "title": "Home",
            "description": "How many lights are on, the main room's colour as a dot; the popover: the rooms as colour tiles that toggle on a tap, a room's lights inline with sliders, the scenes, the sensors, everything on or off. Hidden until a bridge is paired.",
            "refresh": {
              "every": 60,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "settings": [
              {
                "kind": "text",
                "id": "main_room",
                "label": "Main room",
                "placeholder": "Living room",
                "description": "The room the item's tooltip names and whose scenes its popover lists. Empty: the room with most lights on.",
                "default": ""
              },
              {
                "kind": "list",
                "id": "scenes",
                "label": "Scenes",
                "placeholder": "Relax",
                "description": "Scene names (or ids like scene:living-room/relax) listed in the popover, in this order. Empty: the main room's scenes.",
                "default": []
              }
            ],
            "mocks": {
              "on": {
                "title": "Lights on, the main room's colour as a dot",
                "item": {
                  "icon": "󰌵",
                  "title": "5 on",
                  "tooltip": "5 of 12 lights on · Living room 72%"
                }
              },
              "off": {
                "title": "All lights off",
                "item": {
                  "icon": "󰌶",
                  "color": "muted",
                  "tooltip": "All lights off"
                }
              },
              "away": {
                "title": "Bridge not answering, last state kept",
                "item": {
                  "icon": "󰌶",
                  "color": "muted",
                  "stale": true,
                  "tooltip": "All lights off"
                }
              },
              "unpaired": {
                "title": "Bridge not paired",
                "item": {
                  "icon": "󰌶",
                  "color": "muted",
                  "stale": true,
                  "tooltip": "Hue: the bridge did not answer"
                }
              },
              "none": {
                "title": "No bridge configured",
                "item": {
                  "hidden": true
                }
              }
            },
            "keys": [
              {
                "keys": "up",
                "title": "Move over the rooms; walk an opened room's lights"
              },
              {
                "keys": "enter",
                "title": "Open the room under the cursor; toggle the light under it"
              },
              {
                "keys": "space",
                "title": "Toggle the room (or the light) under the cursor"
              },
              {
                "keys": "right",
                "title": "Brighter by 5 (shift: 20); left dims"
              },
              {
                "keys": "backspace",
                "title": "Close the opened room"
              },
              {
                "keys": "1",
                "title": "Play the scene with that digit (1 to 9)"
              },
              {
                "keys": "e",
                "title": "Everything on"
              },
              {
                "keys": "x",
                "title": "All off"
              },
              {
                "keys": "p",
                "title": "Open Rooms in pal"
              },
              {
                "keys": "r",
                "title": "Read the bridge again"
              }
            ]
          }
        },
        "links": {
          "toggle": {
            "description": "Toggle a room, or set it",
            "params": {
              "room": {
                "description": "The room's name, slug or id (living-room, room:living-room)",
                "required": true
              },
              "on": {
                "description": "Set rather than toggle",
                "type": "boolean"
              }
            }
          },
          "scene": {
            "description": "Play a scene",
            "params": {
              "name": {
                "description": "The scene's name or id (relax, scene:living-room/relax)",
                "required": true
              },
              "room": {
                "description": "The room, when the name is in several"
              },
              "dynamic": {
                "description": "Play its palette dynamically",
                "type": "boolean"
              }
            }
          },
          "off": {
            "description": "Every light off"
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/hue",
      "tagline": "Every Hue light, room and scene, live, under the keys",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/hue/screenshots/1-rooms-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/1-rooms.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/2-light-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/2-light.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/3-room-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/3-room.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/4-scenes-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/4-scenes.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/5-sensors-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/5-sensors.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/6-setup-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/6-setup.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover-room-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover-room.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/hue/screenshots/1-rooms.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/2-light.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/3-room.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/4-scenes.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/5-sensors.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/6-setup.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover-room.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/hue/screenshots/1-rooms-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/2-light-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/3-room-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/4-scenes-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/5-sensors-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/6-setup-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover-room-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/hue/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "home",
          "title": "Home",
          "description": "How many lights are on, the main room's colour as a dot; the popover: the rooms as colour tiles that toggle on a tap, a room's lights inline with sliders, the scenes, the sensors, everything on or off. Hidden until a bridge is paired.",
          "refresh": {
            "every": 60,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "toggle",
          "url": "pal://hue/toggle?room=\u003croom\u003e",
          "cli": "pal call hue/toggle room=\u003croom\u003e",
          "description": "Toggle a room, or set it",
          "params": [
            {
              "name": "room",
              "description": "The room's name, slug or id (living-room, room:living-room)",
              "required": true
            },
            {
              "name": "on",
              "description": "Set rather than toggle",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "scene",
          "url": "pal://hue/scene?name=\u003cname\u003e",
          "cli": "pal call hue/scene name=\u003cname\u003e",
          "description": "Play a scene",
          "params": [
            {
              "name": "name",
              "description": "The scene's name or id (relax, scene:living-room/relax)",
              "required": true
            },
            {
              "name": "room",
              "description": "The room, when the name is in several"
            },
            {
              "name": "dynamic",
              "description": "Play its palette dynamically",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "off",
          "url": "pal://hue/off",
          "cli": "pal call hue/off",
          "description": "Every light off",
          "params": []
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "icons",
      "kind": "registry",
      "title": "Icons",
      "description": "Search every Nerd Font glyph by name and copy it, its code point or its class name. A second grid covers the 200k icons Iconify hosts and copies them as SVG.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰠱",
          "bg": "pink"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/icons@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/icons",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "icons",
        "title": "Icons",
        "description": "Search every Nerd Font glyph by name and copy it, its code point or its class name. A second grid covers the 200k icons Iconify hosts and copies them as SVG.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰠱",
            "bg": "pink"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "list",
            "id": "sets",
            "label": "Iconify sets",
            "description": "Set prefixes the Iconify search is limited to (mdi, tabler, lucide, phosphor, simple-icons). Empty: every set.",
            "placeholder": "mdi",
            "default": []
          },
          {
            "kind": "path",
            "id": "save_to",
            "label": "Save SVGs to",
            "description": "Where Save SVG puts an Iconify icon. ~ is expanded.",
            "pick": "folder",
            "default": "~/Downloads"
          }
        ],
        "store": {
          "tagline": "All 11k Nerd Font glyphs, and Iconify's 200k as SVG",
          "category": "reference",
          "features": [
            "All 10,995 Nerd Font glyphs (Material Design, Font Awesome, Codicons, Octicons and more) in one grid",
            "Search by name (`account circle`), by `nf-` name or by code point (`f0009`)",
            "`enter` copies the glyph, `cmd+enter` its code point; the `nf-` name and CSS class copy too",
            "Your last twelve picks lead in a Recent section",
            "Iconify: 200k icons from Tabler, Lucide, Phosphor, Simple Icons and more, copied as SVG or a data URL",
            "The freedesktop icon names scripts can use, each with its glyph"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-grid.png",
              "caption": "The Nerd Font grid, Recent first, then the sets in order"
            },
            {
              "file": "2-search.png",
              "caption": "Searching `github` finds the mark in every set at once, a section per set: Font Awesome, Codicons, Octicons and the rest"
            },
            {
              "file": "3-freedesktop.png",
              "caption": "The freedesktop icon names the SDK's xdg() maps to a glyph"
            },
            {
              "file": "4-actions.png",
              "caption": "Copy the glyph, its code point, its nf- name or the CSS class"
            },
            {
              "file": "5-iconify.png",
              "caption": "Iconify Icons: `arrow` across Material Design Icons, Tabler, Lucide and the rest, each tile its SVG"
            }
          ],
          "actions": [
            {
              "title": "Copy glyph",
              "description": "The character itself.",
              "keys": "enter"
            },
            {
              "title": "Copy code point",
              "description": "`U+F0009`",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy name",
              "description": "`nf-md-account_circle`; on a freedesktop row, `enter` copies the name.",
              "keys": "cmd+shift+n"
            },
            {
              "title": "Copy CSS class",
              "description": "`nf nf-md-account_circle`",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy SVG",
              "description": "On an Iconify tile: the whole SVG, `currentColor` kept.",
              "keys": "enter"
            },
            {
              "title": "Copy as data URL",
              "description": "On an Iconify tile: `data:image/svg+xml;utf8,...` for an `{ image }` icon or a CSS background.",
              "keys": "cmd+shift+d"
            },
            {
              "title": "Open on Iconify",
              "description": "The icon's page on icon-sets.iconify.design.",
              "keys": "cmd+o"
            },
            {
              "title": "Save SVG",
              "description": "The SVG into the `save_to` folder, `-2` when the name is taken.",
              "keys": "cmd+s"
            }
          ]
        },
        "palettes": {
          "icons": {
            "tier": "catalog",
            "title": "Nerd Font icons",
            "kind": "grid",
            "description": "The glyphs of the Symbols Nerd Font the app bundles, by set; recently copied glyphs first.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy glyph"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy code point"
              },
              {
                "keys": "cmd+shift+n",
                "title": "Copy name"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy CSS class"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in the grid.",
                "min": 4,
                "max": 16,
                "default": 10
              }
            ]
          },
          "freedesktop": {
            "tier": "catalog",
            "title": "Freedesktop icon names",
            "kind": "grid",
            "description": "The freedesktop icon names pal maps to a glyph (`xdg()` in the SDK), for a script's `icon_xdg`.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy name"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy glyph"
              },
              {
                "keys": "cmd+shift+u",
                "title": "Copy code point"
              }
            ]
          },
          "iconify": {
            "tier": "normal",
            "title": "Iconify Icons",
            "kind": "grid",
            "description": "Every set Iconify hosts, searched over its API as you type; the tiles are the SVGs. Copy the SVG, the name, a data URL, open the icon's page or save the file.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy SVG"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy name (mdi:home)"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Copy as data URL"
              },
              {
                "keys": "cmd+o",
                "title": "Open on icon-sets.iconify.design"
              },
              {
                "keys": "cmd+s",
                "title": "Save the SVG to a folder"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in the grid.",
                "min": 4,
                "max": 16,
                "default": 8
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/icons",
      "tagline": "All 11k Nerd Font glyphs, and Iconify's 200k as SVG",
      "category": "reference",
      "screenshots": [
        "https://pal.cagdas.io/extensions/icons/screenshots/1-grid-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/1-grid.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/3-freedesktop-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/3-freedesktop.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/5-iconify-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/5-iconify.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/icons/screenshots/1-grid.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/3-freedesktop.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/5-iconify.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/icons/screenshots/1-grid-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/3-freedesktop-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/icons/screenshots/5-iconify-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "images",
      "kind": "registry",
      "title": "Images",
      "description": "Compress, resize, convert, crop and strip the images selected in Finder or on the clipboard, with the tools already on your machine. Every result is saved next to the original, its path copied.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰋩",
          "bg": "pink"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/images@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/images",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "images",
        "title": "Images",
        "description": "Compress, resize, convert, crop and strip the images selected in Finder or on the clipboard, with the tools already on your machine. Every result is saved next to the original, its path copied.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰋩",
            "bg": "pink"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "replace",
            "label": "Replace the original",
            "text": "Write the result over the source instead of next to it (a copy is kept for Restore original)",
            "default": false
          },
          {
            "kind": "number",
            "id": "quality",
            "label": "Quality",
            "description": "For the lossy encoders (JPEG, WebP, AVIF, HEIC, pngquant's floor is 25 below it).",
            "min": 1,
            "max": 100,
            "default": 80
          },
          {
            "kind": "select",
            "id": "web_format",
            "label": "Web format",
            "description": "What Optimise for web writes: the source's format, or WebP or AVIF.",
            "options": [
              {
                "id": "keep",
                "title": "Keep the format"
              },
              {
                "id": "webp",
                "title": "WebP"
              },
              {
                "id": "avif",
                "title": "AVIF"
              }
            ],
            "default": "keep"
          },
          {
            "kind": "number",
            "id": "web_max",
            "label": "Web size cap",
            "description": "Optimise for web shrinks the long side to at most this many pixels; smaller images are left at their size.",
            "min": 100,
            "max": 10000,
            "unit": "px",
            "default": 2000
          },
          {
            "kind": "boolean",
            "id": "thumbnails",
            "label": "Thumbnails",
            "text": "Show a thumbnail on each row and in the detail pane (sips or ImageMagick, cached)",
            "default": true
          },
          {
            "kind": "text",
            "id": "pad_color",
            "label": "Pad colour",
            "description": "What Pad to a square fills with, as hex.",
            "placeholder": "#ffffff",
            "default": "#ffffff"
          },
          {
            "kind": "secret",
            "id": "tinypng_api_key",
            "label": "TinyPNG API key",
            "description": "From tinypng.com/developers (500 compressions a month free). Adds Compress with TinyPNG to every row.",
            "placeholder": "your key"
          },
          {
            "kind": "list",
            "id": "tools",
            "label": "Tools",
            "description": "The encoders in the order they are tried; one left out is never used. Resizing and the other geometry are sips's on macOS whenever it is listed; ImageMagick is the fallback for everything.",
            "placeholder": "pngquant",
            "default": [
              "pngquant",
              "oxipng",
              "optipng",
              "cjpeg",
              "jpegtran",
              "cwebp",
              "avifenc",
              "gifsicle",
              "exiftool",
              "sips",
              "magick"
            ]
          }
        ],
        "store": {
          "tagline": "Compress, resize and convert images, locally",
          "category": "media",
          "features": [
            "Works on the images at hand: the Finder selection, the clipboard or a typed path",
            "Compress with whatever is installed (pngquant, oxipng, mozjpeg, cwebp, avifenc, ImageMagick), or TinyPNG with a key",
            "Resize, convert (PNG, JPEG, WebP, AVIF, HEIC, PDF), rotate, crop, grayscale and strip metadata",
            "Optimise for web: resize, compress and strip in one step, with the size saved per image",
            "Make an icon set (`.icns`, favicon, touch and Android sizes); read the text in an image",
            "Results land next to the original with a suffix; Replace keeps the original for Restore"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-images.png",
              "caption": "The images at hand: the Finder selection and the clipboard, each with its size and dimensions, the result of a compression under Results"
            },
            {
              "file": "2-actions.png",
              "caption": "Every operation on a row: compress, optimise for web, resize, convert, rotate, crop, strip, grayscale, icon set, OCR, info"
            },
            {
              "file": "3-detail.png",
              "caption": "The detail pane: the picture, its size, dimensions, format, colour profile and camera"
            },
            {
              "file": "4-resize.png",
              "caption": "Resize: the presets and a typed size, each row saying the pixels it lands on"
            },
            {
              "file": "5-convert.png",
              "caption": "Convert: the formats, each row naming the tool that writes it, a missing tool named"
            },
            {
              "file": "6-web.png",
              "caption": "Optimise for web: the before and after of every image, the saving as a tag, the total saved as the headline"
            }
          ],
          "actions": [
            {
              "title": "Compress",
              "description": "Lossy at the quality; the smaller of the encoders' results, or nothing when the file is already small.",
              "keys": "enter"
            },
            {
              "title": "Optimise for web",
              "description": "Cap the long side, encode, strip; a view with the before and after.",
              "keys": "cmd+enter"
            },
            {
              "title": "Compress losslessly",
              "description": "oxipng, jpegtran, cwebp -lossless, gifsicle: the pixels untouched.",
              "keys": "cmd+l"
            },
            {
              "title": "Compress with TinyPNG",
              "description": "With an API key set.",
              "keys": "cmd+t"
            },
            {
              "title": "Resize…",
              "description": "Presets, or a typed size: 800, x600, 800x600, 50%, 2x.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Convert…",
              "description": "PNG, JPEG, WebP, AVIF, HEIC, PDF, TIFF, GIF.",
              "keys": "cmd+shift+v"
            },
            {
              "title": "Rotate or flip…",
              "description": "90° either way, 180°, mirror.",
              "keys": "cmd+shift+o"
            },
            {
              "title": "Crop or pad…",
              "description": "Square, 16:9, 4:3, 3:2, 9:16 centred; pad to a square.",
              "keys": "cmd+shift+a"
            },
            {
              "title": "Strip metadata",
              "description": "EXIF, XMP, comments, the ICC profile; lossless for PNG and JPEG.",
              "keys": "cmd+shift+m"
            },
            {
              "title": "Grayscale",
              "keys": "cmd+g"
            },
            {
              "title": "Make an icon set",
              "description": "A folder with the .iconset, .icns, favicon.ico and the web sizes.",
              "keys": "cmd+shift+f"
            },
            {
              "title": "Copy text (OCR)",
              "keys": "cmd+shift+t"
            },
            {
              "title": "Copy info",
              "description": "The detail pane's lines as text.",
              "keys": "cmd+shift+i"
            },
            {
              "title": "Copy path",
              "keys": "cmd+c"
            },
            {
              "title": "Copy image",
              "description": "The picture onto the clipboard (PNG and JPEG); other formats as a file.",
              "keys": "cmd+shift+p"
            },
            {
              "title": "Open",
              "keys": "cmd+o"
            },
            {
              "title": "Reveal in Finder",
              "keys": "cmd+shift+e"
            },
            {
              "title": "Restore original",
              "description": "On a result that replaced its source.",
              "keys": "cmd+shift+z"
            },
            {
              "title": "Move result to Trash",
              "description": "Asks first; the source stays.",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "images": {
            "title": "Images",
            "kind": "input",
            "description": "The images selected in Finder, on the clipboard or at a typed path; every operation an action on a row, the results next to their sources.",
            "keys": [
              {
                "keys": "enter",
                "title": "Compress"
              },
              {
                "keys": "cmd+enter",
                "title": "Optimise for web"
              },
              {
                "keys": "cmd+l",
                "title": "Compress losslessly"
              },
              {
                "keys": "cmd+t",
                "title": "Compress with TinyPNG (with a key)"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Resize…"
              },
              {
                "keys": "cmd+shift+v",
                "title": "Convert…"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Rotate or flip…"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Crop or pad…"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Strip metadata"
              },
              {
                "keys": "cmd+g",
                "title": "Grayscale"
              },
              {
                "keys": "cmd+shift+f",
                "title": "Make an icon set"
              },
              {
                "keys": "cmd+shift+t",
                "title": "Copy text (OCR)"
              },
              {
                "keys": "cmd+shift+i",
                "title": "Copy info"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+shift+p",
                "title": "Copy image"
              },
              {
                "keys": "cmd+o",
                "title": "Open"
              },
              {
                "keys": "cmd+shift+e",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+shift+z",
                "title": "Restore original (a replaced result)"
              },
              {
                "keys": "cmd+d",
                "title": "Move result to Trash"
              },
              {
                "keys": "tab",
                "title": "Mark a row; x too while nothing is typed"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/images",
      "tagline": "Compress, resize and convert images, locally",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/images/screenshots/1-images-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/1-images.png",
        "https://pal.cagdas.io/extensions/images/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/images/screenshots/3-detail-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/3-detail.png",
        "https://pal.cagdas.io/extensions/images/screenshots/4-resize-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/4-resize.png",
        "https://pal.cagdas.io/extensions/images/screenshots/5-convert-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/5-convert.png",
        "https://pal.cagdas.io/extensions/images/screenshots/6-web-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/6-web.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/images/screenshots/1-images.png",
        "https://pal.cagdas.io/extensions/images/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/images/screenshots/3-detail.png",
        "https://pal.cagdas.io/extensions/images/screenshots/4-resize.png",
        "https://pal.cagdas.io/extensions/images/screenshots/5-convert.png",
        "https://pal.cagdas.io/extensions/images/screenshots/6-web.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/images/screenshots/1-images-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/3-detail-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/4-resize-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/5-convert-dark.png",
        "https://pal.cagdas.io/extensions/images/screenshots/6-web-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "immich",
      "kind": "registry",
      "title": "Immich",
      "description": "Search your Immich photo library by what is in the picture and browse the results as a grid. Albums, people and today's memories are one keystroke away, and a photo opens, copies or downloads from the list.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M11.9863.2695c-2.409 0-5.207 1.091-5.207 3.8946v.1523c1.3428.597 2.9347 1.6629 4.4121 2.9707 1.5713 1.3912 2.8374 2.8821 3.6524 4.2871 1.3997-2.5034 2.3358-5.4784 2.3476-7.373V4.164c0-2.8035-2.796-3.8946-5.205-3.8946m7.5117 4.4903c-.3778-.0081-.7747.0502-1.1914.1855-.0366.0118-.086.0278-.1445.0469-.1525 1.4611-.6756 3.304-1.4629 5.1133-.8373 1.9243-1.8627 3.5898-2.9472 4.7988 2.8132.558 5.9307.5273 7.7363-.0469.0126-.004.0246-.0065.0351-.0097 2.6665-.8666 2.84-3.8636 2.0957-6.1543-.6279-1.9332-2.081-3.89-4.121-3.9336m-14.996.039C2.4618 4.8424 1.0088 6.7973.3809 8.7305c-.7442 2.291-.5708 5.288 2.0957 6.1543l.1445.0468c.982-1.0926 2.4873-2.2761 4.1875-3.2773 1.8088-1.0646 3.619-1.808 5.207-2.1484-1.9483-2.1049-4.4884-3.9132-6.287-4.5098l-.0352-.0117c-.4167-.1354-.8136-.1936-1.1914-.1856m4.6718 6.7578c-2.6038 1.2025-5.1088 3.0598-6.2324 4.586l-.0215.0293c-1.6478 2.2683-.0272 4.7953 1.9219 6.211 1.9487 1.4159 4.8518 2.1765 6.5-.0919.0228-.0309.0536-.071.0898-.121-.7356-1.2717-1.396-3.0718-1.8222-4.9981-.4534-2.0492-.6023-4-.4356-5.6153m1.0723 3.338c.3387 2.8478 1.3315 5.8037 2.4355 7.3437l.0215.0293c1.6478 2.2683 4.551 1.5078 6.5.0918 1.9487-1.416 3.5697-3.943 1.9219-6.211-.0228-.0309-.0517-.073-.0879-.123-1.4367.3066-3.3522.3794-5.3164.1894-2.089-.2017-3.9895-.6623-5.4746-1.3203",
          "box": 24,
          "bg": "#4250AF"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/immich@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/immich",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "immich",
        "title": "Immich",
        "description": "Search your Immich photo library by what is in the picture and browse the results as a grid. Albums, people and today's memories are one keystroke away, and a photo opens, copies or downloads from the list.",
        "version": "0.1.0",
        "keywords": [
          "photos",
          "pictures",
          "immich"
        ],
        "icon": {
          "tile": {
            "svg": "M11.9863.2695c-2.409 0-5.207 1.091-5.207 3.8946v.1523c1.3428.597 2.9347 1.6629 4.4121 2.9707 1.5713 1.3912 2.8374 2.8821 3.6524 4.2871 1.3997-2.5034 2.3358-5.4784 2.3476-7.373V4.164c0-2.8035-2.796-3.8946-5.205-3.8946m7.5117 4.4903c-.3778-.0081-.7747.0502-1.1914.1855-.0366.0118-.086.0278-.1445.0469-.1525 1.4611-.6756 3.304-1.4629 5.1133-.8373 1.9243-1.8627 3.5898-2.9472 4.7988 2.8132.558 5.9307.5273 7.7363-.0469.0126-.004.0246-.0065.0351-.0097 2.6665-.8666 2.84-3.8636 2.0957-6.1543-.6279-1.9332-2.081-3.89-4.121-3.9336m-14.996.039C2.4618 4.8424 1.0088 6.7973.3809 8.7305c-.7442 2.291-.5708 5.288 2.0957 6.1543l.1445.0468c.982-1.0926 2.4873-2.2761 4.1875-3.2773 1.8088-1.0646 3.619-1.808 5.207-2.1484-1.9483-2.1049-4.4884-3.9132-6.287-4.5098l-.0352-.0117c-.4167-.1354-.8136-.1936-1.1914-.1856m4.6718 6.7578c-2.6038 1.2025-5.1088 3.0598-6.2324 4.586l-.0215.0293c-1.6478 2.2683-.0272 4.7953 1.9219 6.211 1.9487 1.4159 4.8518 2.1765 6.5-.0919.0228-.0309.0536-.071.0898-.121-.7356-1.2717-1.396-3.0718-1.8222-4.9981-.4534-2.0492-.6023-4-.4356-5.6153m1.0723 3.338c.3387 2.8478 1.3315 5.8037 2.4355 7.3437l.0215.0293c1.6478 2.2683 4.551 1.5078 6.5.0918 1.9487-1.416 3.5697-3.943 1.9219-6.211-.0228-.0309-.0517-.073-.0879-.123-1.4367.3066-3.3522.3794-5.3164.1894-2.089-.2017-3.9895-.6623-5.4746-1.3203",
            "box": 24,
            "bg": "#4250AF"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "url",
            "required": true,
            "label": "URL",
            "placeholder": "https://immich.example.com",
            "description": "Where the Immich API answers, scheme included; no trailing slash needed.",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "api_key",
            "required": true,
            "label": "API key",
            "placeholder": "keychain:pal/immich-api_key",
            "description": "From Immich › Account Settings › API Keys. Reading needs asset.read, album.read, person.read, memory.read and asset.download; favouriting asset.update and adding to albums albumAsset.create. Stored as a keychain: or env: reference.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "web_url",
            "label": "Web address",
            "placeholder": "https://photos.example.com",
            "description": "Where Open in Immich and Copy link point when the site has another name than the API (a tailnet API behind a public site). Empty: the URL above.",
            "default": ""
          },
          {
            "kind": "path",
            "id": "download_to",
            "label": "Download to",
            "pick": "folder",
            "placeholder": "~/Downloads",
            "description": "Where Download preview and Download original write, named `\u003cdate\u003e_\u003cfile\u003e`.",
            "default": "~/Downloads"
          }
        ],
        "store": {
          "tagline": "Search your Immich photos by what is in them",
          "category": "media",
          "features": [
            "Search by what is in the photo (\"a receipt\", \"dog on the beach\"), or by file name",
            "Narrow by date and place with `since:2025`, `in:2023` or `in:Ataşehir`; filter to videos or favourites",
            "A side pane with the photo large, when and where it was taken, the camera, the people and the albums",
            "`enter` opens it in Immich; copy the link or the picture, download it, favourite it or add it to an album",
            "Albums, people and On this day as lists of their own",
            "Thumbnails are cached, so a second look is instant"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-recent.png",
              "caption": "Nothing typed: the newest uploads, the pane open on the first"
            },
            {
              "file": "2-search.png",
              "caption": "A CLIP search: what is in the picture, the place and date on every tile"
            },
            {
              "file": "3-actions.png",
              "caption": "What a photo can do: open, copy, download, favourite, add to an album, Quick Look"
            },
            {
              "file": "4-albums.png",
              "caption": "Albums: the cover, the count, the dates, the library's numbers on top"
            },
            {
              "file": "5-people.png",
              "caption": "People by face, favourites first"
            },
            {
              "file": "6-memories.png",
              "caption": "On this day: a row per year, Enter opens that year's photos"
            }
          ],
          "actions": [
            {
              "title": "Open in Immich",
              "description": "The photo's page on the web address.",
              "keys": "enter"
            },
            {
              "title": "Copy link",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy image",
              "description": "The preview onto the clipboard as a picture.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Download preview",
              "description": "The 1440 px JPEG into `download_to`.",
              "keys": "cmd+s"
            },
            {
              "title": "Download original",
              "description": "The file as uploaded (a HEIC, an ARW, a video).",
              "keys": "cmd+shift+s"
            },
            {
              "title": "Favourite / Unfavourite",
              "keys": "cmd+f"
            },
            {
              "title": "Add to album…",
              "description": "A picker of your albums, or a new one.",
              "keys": "cmd+shift+a"
            },
            {
              "title": "Quick Look",
              "description": "The preview in Quick Look (macOS).",
              "keys": "cmd+y"
            }
          ]
        },
        "palettes": {
          "immich": {
            "title": "Immich",
            "kind": "grid",
            "fallback": "Search Immich for “{query}”",
            "description": "Type what is in the picture and Immich's CLIP search answers as a grid; a file name searches by name; nothing typed lists the newest uploads. since:, before:, in: narrow it; the dropdown picks photos, videos, favourites or the archive.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Immich"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy link"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy image"
              },
              {
                "keys": "cmd+s",
                "title": "Download preview"
              },
              {
                "keys": "cmd+shift+s",
                "title": "Download original"
              },
              {
                "keys": "cmd+f",
                "title": "Favourite or unfavourite"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Add to album…"
              },
              {
                "keys": "cmd+y",
                "title": "Quick Look"
              },
              {
                "keys": "cmd+i",
                "title": "The detail pane"
              },
              {
                "keys": "tab",
                "title": "Photos, videos, favourites, archive"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in every grid.",
                "min": 3,
                "max": 10,
                "default": 6
              }
            ]
          },
          "albums": {
            "title": "Immich Albums",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "description": "Every album with its cover, count and dates; Enter opens the album as a grid, cmd+enter opens it in Immich. The library's numbers lead the list.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the album"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in Immich"
              },
              {
                "keys": "cmd+c",
                "title": "Copy link"
              }
            ]
          },
          "people": {
            "title": "Immich People",
            "kind": "list",
            "lazy": true,
            "ttl": 600,
            "description": "The people Immich has named, favourites first, each with their face; Enter lists a person's photos as a grid.",
            "keys": [
              {
                "keys": "enter",
                "title": "The person's photos"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in Immich"
              },
              {
                "keys": "cmd+c",
                "title": "Copy link"
              }
            ]
          },
          "memories": {
            "title": "On This Day",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 1800,
            "description": "Immich's memories for today: a row per past year with the count and the places; Enter opens that year's photos as a grid.",
            "keys": [
              {
                "keys": "enter",
                "title": "That year's photos"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in Immich"
              }
            ]
          }
        },
        "links": {
          "search": {
            "description": "Open the Immich grid on a search",
            "params": {
              "q": {
                "description": "What to search for; empty lists the newest uploads. since:, before: and in: work here too"
              },
              "filter": {
                "description": "photos, videos, favourites or archived"
              }
            }
          },
          "album": {
            "description": "Open an album as a grid",
            "params": {
              "name": {
                "description": "The album's name (case does not matter)"
              },
              "id": {
                "description": "Or its id"
              }
            }
          },
          "person": {
            "description": "Open a person's photos as a grid",
            "params": {
              "name": {
                "description": "The person's name as Immich has it (case does not matter)"
              },
              "id": {
                "description": "Or their id"
              }
            }
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/immich",
      "tagline": "Search your Immich photos by what is in them",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/immich/screenshots/1-recent-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/1-recent.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/4-albums-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/4-albums.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/5-people-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/5-people.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/6-memories-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/6-memories.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/immich/screenshots/1-recent.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/4-albums.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/5-people.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/6-memories.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/immich/screenshots/1-recent-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/4-albums-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/5-people-dark.png",
        "https://pal.cagdas.io/extensions/immich/screenshots/6-memories-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "search",
          "url": "pal://immich/search",
          "cli": "pal call immich/search",
          "description": "Open the Immich grid on a search",
          "params": [
            {
              "name": "q",
              "description": "What to search for; empty lists the newest uploads. since:, before: and in: work here too"
            },
            {
              "name": "filter",
              "description": "photos, videos, favourites or archived"
            }
          ]
        },
        {
          "route": "album",
          "url": "pal://immich/album",
          "cli": "pal call immich/album",
          "description": "Open an album as a grid",
          "params": [
            {
              "name": "name",
              "description": "The album's name (case does not matter)"
            },
            {
              "name": "id",
              "description": "Or its id"
            }
          ]
        },
        {
          "route": "person",
          "url": "pal://immich/person",
          "cli": "pal call immich/person",
          "description": "Open a person's photos as a grid",
          "params": [
            {
              "name": "name",
              "description": "The person's name as Immich has it (case does not matter)"
            },
            {
              "name": "id",
              "description": "Or their id"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "make",
      "kind": "registry",
      "title": "Makefile Targets",
      "description": "Every Makefile target under your project folders in one list. Enter runs it in a terminal or in the background, with variables typed in first.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰣪",
          "bg": "orange"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/make@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/make",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "make",
        "title": "Makefile Targets",
        "description": "Every Makefile target under your project folders in one list. Enter runs it in a terminal or in the background, with variables typed in first.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰣪",
            "bg": "orange"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "list",
            "id": "projects",
            "local": true,
            "label": "Project folders",
            "description": "Folders scanned two levels deep for a Makefile, makefile or GNUmakefile. ~ is expanded.",
            "placeholder": "~/proj",
            "default": [
              "~/proj"
            ]
          },
          {
            "kind": "select",
            "id": "terminal",
            "label": "Run in",
            "description": "Where Run puts make. A terminal keeps its window open until you press Enter; background runs it unseen and toasts the exit status (the output opens in the panel when it failed; a run past 8 s is left to finish on its own). On Linux the terminal is $TERMINAL, else kitty, foot, alacritty, xterm.",
            "options": [
              {
                "id": "auto",
                "title": "Terminal (auto)"
              },
              {
                "id": "background",
                "title": "Background"
              },
              {
                "id": "kitty",
                "title": "kitty"
              },
              {
                "id": "Terminal",
                "title": "Terminal"
              },
              {
                "id": "iTerm2",
                "title": "iTerm2"
              },
              {
                "id": "Ghostty",
                "title": "Ghostty"
              },
              {
                "id": "Alacritty",
                "title": "Alacritty"
              }
            ],
            "default": "auto"
          }
        ],
        "store": {
          "tagline": "Every Makefile target under your projects, Enter runs it",
          "category": "developer",
          "features": [
            "Every target of every Makefile in your project folders, one section per project",
            "Each target's `## description` shown beside it",
            "`enter` runs `make \u003ctarget\u003e` in a terminal in the project folder, left open so you can read the output",
            "Or run it in the background: a notice with the exit status, the full output when it failed",
            "The side pane shows the recipe; `cmd+l` opens the whole Makefile, `cmd+c` copies the command"
          ],
          "permissions": [
            "make",
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-targets.png",
              "caption": "Every target of the Makefiles under the configured folders, a section per project, its ## description under the name"
            },
            {
              "file": "2-recipe.png",
              "caption": "The detail pane (cmd+I): the Makefile and the target on top, its description, then its recipe"
            },
            {
              "file": "3-makefile.png",
              "caption": "Show Makefile (cmd+L): the whole file in the panel, the ## comments that describe the targets included"
            },
            {
              "file": "4-actions.png",
              "caption": "What a target can do: run it, copy the make command, open the project, show the Makefile"
            }
          ],
          "actions": [
            {
              "title": "Run",
              "description": "make \u003ctarget\u003e in a terminal in the project folder, or in the background per the setting; the bar takes optional words after the target first (VERBOSE=1, -j4).",
              "keys": "enter"
            },
            {
              "title": "Copy command",
              "description": "make -C \u003cdir\u003e \u003ctarget\u003e.",
              "keys": "cmd+c"
            },
            {
              "title": "Open project",
              "description": "The project folder in the file manager.",
              "keys": "cmd+o"
            },
            {
              "title": "Show Makefile",
              "description": "The whole file in the panel.",
              "keys": "cmd+l"
            }
          ]
        },
        "palettes": {
          "make": {
            "title": "Makefile Targets",
            "kind": "list",
            "description": "Every target of every Makefile in the project folders, one section per project.",
            "keys": [
              {
                "keys": "enter",
                "title": "Run the target (variables or flags typed in the bar go after it; blank runs it plain)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the make command"
              },
              {
                "keys": "cmd+o",
                "title": "Open the project folder"
              },
              {
                "keys": "cmd+l",
                "title": "Show the Makefile"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/make",
      "tagline": "Every Makefile target under your projects, Enter runs it",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/make/screenshots/1-targets-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/1-targets.png",
        "https://pal.cagdas.io/extensions/make/screenshots/2-recipe-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/2-recipe.png",
        "https://pal.cagdas.io/extensions/make/screenshots/3-makefile-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/3-makefile.png",
        "https://pal.cagdas.io/extensions/make/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/4-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/make/screenshots/1-targets.png",
        "https://pal.cagdas.io/extensions/make/screenshots/2-recipe.png",
        "https://pal.cagdas.io/extensions/make/screenshots/3-makefile.png",
        "https://pal.cagdas.io/extensions/make/screenshots/4-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/make/screenshots/1-targets-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/2-recipe-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/3-makefile-dark.png",
        "https://pal.cagdas.io/extensions/make/screenshots/4-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "maps",
      "kind": "registry",
      "title": "Maps",
      "description": "Search places and get directions in Google Maps or Apple Maps without leaving the keyboard. Type a route like `home \u003e work`, keep saved places, and add a Places API key for autocomplete.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰗵",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/maps@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/maps",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "maps",
        "title": "Maps",
        "description": "Search places and get directions in Google Maps or Apple Maps without leaving the keyboard. Type a route like `home \u003e work`, keep saved places, and add a Places API key for autocomplete.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰗵",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "app",
            "label": "Open in",
            "description": "Which app the rows open. Apple Maps is macOS only (a `maps://` url); Copy link always copies a web url.",
            "options": [
              {
                "id": "google",
                "title": "Google Maps (the browser)"
              },
              {
                "id": "apple",
                "title": "Apple Maps"
              }
            ],
            "default": "google"
          },
          {
            "kind": "text",
            "id": "home",
            "label": "Home",
            "description": "An address or place name; the Home row and the “from home” directions.",
            "placeholder": "Moda, Kadıköy, İstanbul",
            "default": ""
          },
          {
            "kind": "text",
            "id": "work",
            "label": "Work",
            "description": "Likewise; with both set the empty palette lists the commute both ways.",
            "placeholder": "Levent, İstanbul",
            "default": ""
          },
          {
            "kind": "list",
            "id": "places",
            "label": "Saved places",
            "description": "One per line as `Name = address` (a line without `=` is both). Each is a row: open, directions to it, copy the address.",
            "placeholder": "Gym = Kadıköy Sports Hall, İstanbul",
            "default": []
          },
          {
            "kind": "secret",
            "id": "api_key",
            "label": "Places API key",
            "description": "Optional. A Google Cloud key with Places API (New) enabled: place predictions appear under the rows as you type (autocomplete requests are billed by Google past the monthly free credit). Empty: nothing is fetched, the urls need no key.",
            "placeholder": "AIza…",
            "default": ""
          }
        ],
        "store": {
          "tagline": "Places and directions from the panel, no key needed",
          "category": "productivity",
          "features": [
            "Type a place: search it, or get directions from here, from home or from work",
            "Routes typed as you say them: `home \u003e work`, `istanbul to ankara`; the way back as the second row",
            "Pick driving, transit, walking or cycling (`tab` cycles)",
            "Home, work, your commute and every saved place before you type, with Copy address and Copy link",
            "Opens in Google Maps or Apple Maps, your choice; autocomplete with a Places API key",
            "`go: coffee` or `maps: home \u003e work` at the root answers inline"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-places.png",
              "caption": "Nothing typed: Home, Work, the commute both ways and the saved places"
            },
            {
              "file": "2-search.png",
              "caption": "kadıköy typed: Search, directions from here, home and work, a saved place that matches"
            },
            {
              "file": "3-route.png",
              "caption": "home \u003e work: the route and its reverse, walking chosen as the mode"
            },
            {
              "file": "4-autocomplete.png",
              "caption": "With a Places API key: predictions under the rows"
            },
            {
              "file": "5-actions.png",
              "caption": "What a place can do: open, directions from here, from home, from work, copy the address or the link"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "The place in the chosen app; on a route row, the directions.",
              "keys": "enter"
            },
            {
              "title": "Directions from here",
              "description": "From the current location to the place.",
              "keys": "cmd+enter"
            },
            {
              "title": "Directions from home",
              "keys": "cmd+h"
            },
            {
              "title": "Directions from work",
              "keys": "cmd+w"
            },
            {
              "title": "Copy address",
              "keys": "cmd+c"
            },
            {
              "title": "Copy link",
              "description": "The web url of what Enter would open.",
              "keys": "cmd+l"
            },
            {
              "title": "Open in the other app",
              "description": "Apple Maps when Google is chosen, and the other way.",
              "keys": "cmd+shift+o"
            }
          ]
        },
        "palettes": {
          "maps": {
            "title": "Maps",
            "kind": "input",
            "inline": true,
            "match": "^\\s*(?:maps?|go)\\s*:\\s*\\S",
            "description": "Type a place or a route (`home \u003e work`); the filter is the travel mode. Nothing typed lists home, work, the commute and the saved places. `maps:` or `go:` at the root answers inline.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the place or the route"
              },
              {
                "keys": "cmd+enter",
                "title": "Directions from here"
              },
              {
                "keys": "cmd+h",
                "title": "Directions from home"
              },
              {
                "keys": "cmd+w",
                "title": "Directions from work"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the address"
              },
              {
                "keys": "cmd+l",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in the other app"
              },
              {
                "keys": "tab",
                "title": "Next travel mode"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/maps",
      "tagline": "Places and directions from the panel, no key needed",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/maps/screenshots/1-places-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/1-places.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/3-route-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/3-route.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/4-autocomplete-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/4-autocomplete.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/5-actions-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/5-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/maps/screenshots/1-places.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/3-route.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/4-autocomplete.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/5-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/maps/screenshots/1-places-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/3-route-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/4-autocomplete-dark.png",
        "https://pal.cagdas.io/extensions/maps/screenshots/5-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "media",
      "kind": "bundled",
      "title": "Now Playing",
      "description": "Control what is playing in Spotify, Music, a browser or any other player: play, pause and skip from the panel, with the track on the bar.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰝚",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/media@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/media",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "media",
        "title": "Now Playing",
        "description": "Control what is playing in Spotify, Music, a browser or any other player: play, pause and skip from the panel, with the track on the bar.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰝚",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "list",
            "id": "exclude",
            "label": "Leave to another extension",
            "placeholder": "Spotify",
            "description": "Players this extension leaves to another (the Spotify extension's own item, say), by app name (Spotify, Music, Google Chrome) or player id (spotify, music, system): the bar item and the root's Now row skip them; the palette still lists them.",
            "default": []
          }
        ],
        "palettes": {
          "media": {
            "title": "Now Playing",
            "description": "One row per player with the track and its artwork.",
            "kind": "live",
            "keys": [
              {
                "keys": "enter",
                "title": "Play or pause"
              },
              {
                "keys": "cmd+right",
                "title": "Next track"
              },
              {
                "keys": "cmd+left",
                "title": "Previous track"
              },
              {
                "keys": "cmd+c",
                "title": "Copy artist - title"
              },
              {
                "keys": "cmd+o",
                "title": "Open the track in its player"
              }
            ]
          }
        },
        "states": {
          "playing": {
            "description": "A player is playing",
            "kind": "boolean"
          },
          "state": {
            "description": "The strip's player: playing, paused, stopped, or none",
            "kind": "string"
          },
          "app": {
            "description": "The player's name",
            "kind": "string"
          }
        },
        "bar": {
          "now-playing": {
            "title": "Now Playing",
            "description": "The playing track on the strip; a paused player is hidden by its rule (keep it on the strip, muted, by turning that rule's Hidden off), nothing running is hidden either way. The popover shows the cover, the track, a progress bar that ticks and the transport as keys. Re-rendered the moment the track changes (macOS).",
            "refresh": {
              "every": 30,
              "on": [
                "show",
                "wake",
                "media"
              ]
            },
            "settings": [
              {
                "kind": "boolean",
                "id": "artwork",
                "label": "Cover on the bar",
                "text": "Show the cover instead of the note on the menu bar strip",
                "description": "Only a square cover; a 24 pt picture of anything else is a smudge. The popover shows the cover either way.",
                "default": false
              }
            ],
            "mocks": {
              "track": {
                "title": "A track playing",
                "item": {
                  "icon": "",
                  "title": "Weird Fishes/ Arpeggi · Radiohead",
                  "tooltip": "Radiohead - Weird Fishes/ Arpeggi (Music)"
                }
              },
              "artwork": {
                "title": "The cover as the icon (Cover on the bar)",
                "item": {
                  "icon": {
                    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAADyElEQVR4nH3Szwa2WgOG8Y4kIkqKRUmxKOlhUfLEokeKRQ0a5NKgQYMGDTq473C+Q9iDPdm+Py/X+De5b8u3CW2ETWKT2Uib0qa2UTatzddG2/xsJhtjs9psNrvNYXPaXDa3zWPz2li+Q+ggHBKHzEE6lA61g3JoHb4O2uHnMDkYh9Vhc9gdDofT4XK4HR6H18HyXUIX4ZK4ZC7SpXSpXZRL6/J10S4/l8nFuKwum8vucricLpfL7fK4vC6W7xF6CI/EI/OQHqVH7aE8Wo+vh/b4eUwexmP12Dx2j8Pj9Lg8bo/H4/Ww/IAwQAQkAVmADCgD6gAV0AZ8A3TAL2AKMAFrwBawBxwBZ8AVcAc8AW+A5UeEESIiicgiZEQZUUeoiDbiG6EjfhFThIlYI7aIPeKIOCOuiDviiXgjLF8QCoQgEWQCKSgFtUAJWsFXoAU/wSQwglWwCXbBITgFl+AWPIJXYPkxYYyISWKyGBlTxtQxKqaN+cbomF/MFGNi1pgtZo85Ys6YK+aOeWLeGMtPCVNESpKSpciUMqVOUSltyr//Nf6zNWVL2VOOlDPlSrlTnpQ3xfJzwhyRk+RkOTKnzKlzVP6fyt9tOXvOkXPmXDl3zpPz5li+JJQISSLJJFJSSmr5v5W/2yWH5JRcklvySF6J5ReEBaIgKcgKZEFZUBd/hAqOgrPgKrgLnoK3wPIrwgpRkVRkFbKirKirP0IVR8VZcVXcFU/FW2H5H8IP4kPyIfsgP5Qf6s8foQ/Hh/PD9eH+8Hx4P1i+IlQIRaLIFFJRKmr1R0hxKE7FpbgVj+JVWH5D2CAakoasQTaUDXWDav7Pag17w9FwNlwNd8PT8DZYfkfYITqSjqxDdpQddYfqaLv/+lHH1rF3HB1nx9Vxdzwdb4fl94Q9oifpyXpkT9lT96ietufbo3t+PVOP6Vl7tp695+g5e66eu+fpeXssXxNqhCbRZBqpKTW1RmlazVejNT/NpDGaVbNpds2hOTWX5tY8mldj+QPhgBhIBrIBOVAO1ANqoB34DuiB38A0YAbWgW1gHzgGzoFr4B54Bt4Byx8JR8RIMpKNyJFypB5RI+3Id0SP/EamETOyjmwj+8gxco5cI/fIM/KOWP5MOCNmkplsRs6UM/WMmmlnvjN65jczzZiZdWab2WeOmXPmmrlnnpl3xvINoUEYEkNmkIbSUBuUoTV8DdrwM0wGY1gNm2E3HIbTcBluw2N4DZa/EC6IhWQhW5AL5UK9oBbahe+CXvgtTAtmYV3YFvaFY+FcuBbuhWfhXfgL3ZiR8ZsNxlQAAAAASUVORK5CYII="
                  },
                  "title": "Weird Fishes/ Arpeggi · Radiohead",
                  "tooltip": "Radiohead - Weird Fishes/ Arpeggi (Music)"
                }
              },
              "untitled": {
                "title": "A player naming no track",
                "item": {
                  "icon": "",
                  "title": "Safari",
                  "tooltip": "Playing in Safari"
                }
              },
              "paused": {
                "title": "Paused, kept on the bar (While a player runs)",
                "item": {
                  "icon": "",
                  "title": "Weird Fishes/ Arpeggi · Radiohead",
                  "color": "muted",
                  "tooltip": "Radiohead - Weird Fishes/ Arpeggi (Music), paused"
                }
              },
              "silent": {
                "title": "Nothing playing",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "",
                    "tooltip": "Nothing playing"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "space",
                "title": "Pause or play"
              },
              {
                "keys": "right",
                "title": "Next track (cmd+right too)"
              },
              {
                "keys": "left",
                "title": "Previous track (cmd+left too)"
              },
              {
                "keys": "c",
                "title": "Copy artist - title (cmd+c too)"
              },
              {
                "keys": "o",
                "title": "Open the track in its player (cmd+o too)"
              }
            ],
            "rules": [
              {
                "id": "paused",
                "when": "not media.playing",
                "description": "A player that is not playing: off the strip, muted for anyone who keeps it.",
                "hidden": true,
                "color": "muted"
              }
            ]
          },
          "playing": {
            "title": "Playing",
            "description": "Whatever plays, for the glance strip: the Apple TV, Spotify, a browser tab, the newest one leading with its cover, \"artist · where\" and a progress bar, a second one as an \"also\" line. Never on a strip (put it on one by giving it a target in Settings › Bar); ⌥N or a click opens the lead's own view.",
            "strip": false,
            "refresh": {
              "every": 30,
              "on": [
                "show",
                "wake",
                "media"
              ]
            },
            "mocks": {
              "one": {
                "title": "One playing",
                "item": {
                  "icon": "",
                  "title": "Mr. Blue Sky",
                  "tooltip": "Pomplamoose · YouTube on Living Room",
                  "progress": 0.42
                }
              },
              "two": {
                "title": "Two playing (an also line)",
                "item": {
                  "icon": "",
                  "title": "Mr. Blue Sky",
                  "tooltip": "Pomplamoose · YouTube on Living Room",
                  "progress": 0.42,
                  "glance": {
                    "lines": [
                      {
                        "text": "also: Weird Fishes · Spotify",
                        "action": "open:spotify"
                      }
                    ]
                  }
                }
              },
              "paused": {
                "title": "Nothing playing, the last one paused",
                "item": {
                  "icon": "",
                  "title": "Mr. Blue Sky",
                  "tooltip": "Pomplamoose · YouTube on Living Room",
                  "color": "muted"
                }
              }
            }
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Play, pause and skip Spotify, Music, a browser or any MPRIS player",
          "category": "media",
          "features": [
            "One row per player with the track, artist, cover and progress",
            "Every player the system knows about on macOS (a browser, VLC), and MPRIS players on Linux",
            "What your other extensions play comes first: a show on the Apple TV, Spotify on another device, Jellyfin; `enter` opens that extension's own view",
            "The bar item leaves alone a playback another extension's own item already shows, so nothing is on the bar twice",
            "`enter` plays or pauses, `cmd+right` and `cmd+left` skip",
            "`cmd+c` copies `artist - title`, `cmd+o` opens the track or the app",
            "The playing track is found from the root by its title or artist",
            "A bar item with the track; its popover shows the cover, progress and controls",
            "One Playing card on the glance strip for whatever plays, the newest first, with an \"also\" line for a second"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-players.png",
              "caption": "One row per player: a show on the living-room TV from its own extension first, Spotify playing with the position, Music paused, a browser with nothing loaded"
            },
            {
              "file": "2-actions.png",
              "caption": "The actions on a row: open the TV's own remote, pause, next, previous, copy the track"
            },
            {
              "file": "3-root.png",
              "caption": "The playing track found from the root by its title"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the playing track and its artist beside the note",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the cover, the track, a progress bar that ticks, the transport as keys",
              "kind": "bar",
              "box": [
                294,
                64,
                840,
                620
              ]
            },
            {
              "file": "bar-popover-untitled.png",
              "caption": "A player that names no track (a browser): the app, the position, the app's icon in place of a cover",
              "kind": "bar",
              "box": [
                352,
                64,
                840,
                620
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the note in the icon font, the track as the label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "On a player another extension publishes: that extension's own view (the Apple TV's remote, Spotify's lyrics).",
              "keys": "enter"
            },
            {
              "title": "Play or pause",
              "description": "Toggles; the row's tag follows (`cmd+enter` on a published player).",
              "keys": "enter"
            },
            {
              "title": "Next track",
              "keys": "cmd+right"
            },
            {
              "title": "Previous track",
              "keys": "cmd+left"
            },
            {
              "title": "Copy track",
              "description": "artist - title.",
              "keys": "cmd+c"
            },
            {
              "title": "Open in Spotify / Music",
              "description": "The track's url, else the app on macOS.",
              "keys": "cmd+o"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/media",
      "tagline": "Play, pause and skip Spotify, Music, a browser or any MPRIS player",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/media/screenshots/1-players-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/1-players.png",
        "https://pal.cagdas.io/extensions/media/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/media/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover-untitled-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover-untitled.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/media/screenshots/1-players.png",
        "https://pal.cagdas.io/extensions/media/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/media/screenshots/3-root.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/media/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover-untitled.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/media/screenshots/1-players-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/3-root-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/media/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover-untitled-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/media/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "now-playing",
          "title": "Now Playing",
          "description": "The playing track on the strip; a paused player is hidden by its rule (keep it on the strip, muted, by turning that rule's Hidden off), nothing running is hidden either way. The popover shows the cover, the track, a progress bar that ticks and the transport as keys. Re-rendered the moment the track changes (macOS).",
          "refresh": {
            "every": 30,
            "on": [
              "show",
              "wake",
              "media"
            ]
          },
          "refresh_words": "every 30s, when the panel shows, on wake"
        },
        {
          "id": "playing",
          "title": "Playing",
          "description": "Whatever plays, for the glance strip: the Apple TV, Spotify, a browser tab, the newest one leading with its cover, \"artist · where\" and a progress bar, a second one as an \"also\" line. Never on a strip (put it on one by giving it a target in Settings › Bar); ⌥N or a click opens the lead's own view.",
          "refresh": {
            "every": 30,
            "on": [
              "show",
              "wake",
              "media"
            ]
          },
          "refresh_words": "every 30s, when the panel shows, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "menu-bar",
      "kind": "bundled",
      "title": "Menu Bar Items",
      "description": "Every menu item of the app in front as one searchable list: File \u003e Export \u003e PDF with its shortcut; Enter presses it. macOS, over Accessibility.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰍜",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/menu-bar@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/menu-bar",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "menu-bar",
        "title": "Menu Bar Items",
        "description": "Every menu item of the app in front as one searchable list: File \u003e Export \u003e PDF with its shortcut; Enter presses it. macOS, over Accessibility.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰍜",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "The front app's menus, searched and pressed from one list",
          "category": "productivity",
          "features": [
            "Every menu item of the app in front, searchable from the root: `export pdf` finds Preview's item",
            "Each row shows the item, the menus above it, its shortcut and a check mark when it is on",
            "`enter` presses the item, so a dialog it opens lands in the app",
            "Disabled items and separators are left out, and a slow app never delays the panel",
            "macOS only; needs Accessibility, and the row opens the right settings pane when it is missing"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "The front app's menus in one list (TextEdit here): a section per menu, the path as the subtitle, shortcuts as key caps"
            },
            {
              "file": "2-checked.png",
              "caption": "A checked item carries its mark, and Enter Full Screen shows its Globe (fn) key"
            },
            {
              "file": "3-search.png",
              "caption": "Typing narrows by the whole path: format font finds every item of Format \u003e Font"
            },
            {
              "file": "4-root.png",
              "caption": "The rows are root results too: export pdf at the root finds File \u003e Export as PDF… with no palette opened first"
            }
          ],
          "actions": [
            {
              "title": "Press",
              "description": "Hides the panel, then presses the item in the app.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "menu-bar": {
            "title": "Menu Bar Items",
            "tier": "primary",
            "kind": "live",
            "description": "The menus of the app in front; Enter presses the item.",
            "keys": [
              {
                "keys": "enter",
                "title": "Press the menu item"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/menu-bar",
      "tagline": "The front app's menus, searched and pressed from one list",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/2-checked-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/2-checked.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/4-root-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/4-root.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/2-checked.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/4-root.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/2-checked-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/menu-bar/screenshots/4-root-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "minesweeper",
      "kind": "registry",
      "title": "Minesweeper",
      "description": "Classic Minesweeper in the panel, played with the mouse as in the original or one-handed on the arrows. The board, the clock and your best times persist.",
      "version": "0.2.0",
      "icon": {
        "tile": {
          "glyph": "󰚑",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/minesweeper@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/minesweeper",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "minesweeper",
        "title": "Minesweeper",
        "description": "Classic Minesweeper in the panel, played with the mouse as in the original or one-handed on the arrows. The board, the clock and your best times persist.",
        "version": "0.2.0",
        "icon": {
          "tile": {
            "glyph": "󰚑",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "difficulty",
            "label": "Difficulty",
            "description": "The board's size and mines, also picked on the board itself (D, or a click on the level). Applies to the next board, at once when nothing is open yet; a game in progress plays out first.",
            "options": [
              {
                "id": "beginner",
                "title": "Beginner: 9 by 9, 10 mines"
              },
              {
                "id": "intermediate",
                "title": "Intermediate: 16 by 16, 40 mines"
              },
              {
                "id": "expert",
                "title": "Expert: 30 by 16, 99 mines"
              }
            ],
            "default": "beginner"
          },
          {
            "kind": "boolean",
            "id": "clock",
            "label": "Clock",
            "text": "Show the time while you play",
            "description": "Off hides the time beside the face. Your times still count for best times and show when you clear a board. Also T or ⌘K in the game.",
            "default": true
          }
        ],
        "sync": {
          "state": "local",
          "records": {
            "fields": {
              "beginner": {
                "fields": {
                  "played": "sum",
                  "won": "sum"
                }
              },
              "intermediate": {
                "fields": {
                  "played": "sum",
                  "won": "sum"
                }
              },
              "expert": {
                "fields": {
                  "played": "sum",
                  "won": "sum"
                }
              }
            }
          },
          "best-beginner": "min",
          "best-intermediate": "min",
          "best-expert": "min"
        },
        "leaderboards": [
          {
            "id": "daily",
            "title": "Daily board",
            "order": "asc",
            "format": "time",
            "period": "day",
            "min": 1,
            "max": 86400
          },
          {
            "id": "beginner",
            "title": "Beginner",
            "order": "asc",
            "format": "time",
            "min": 0.2,
            "max": 86400
          },
          {
            "id": "intermediate",
            "title": "Intermediate",
            "order": "asc",
            "format": "time",
            "min": 1,
            "max": 86400
          },
          {
            "id": "expert",
            "title": "Expert",
            "order": "asc",
            "format": "time",
            "min": 5,
            "max": 86400
          }
        ],
        "store": {
          "tagline": "Classic Minesweeper, by mouse or one hand on the arrows",
          "category": "fun",
          "features": [
            "The classic board, mine counter and clock, redrawn for the light and dark panel",
            "Mouse as in the original: click opens, right-click flags, both buttons open around a number",
            "One hand: the arrows move, `enter` opens, `/` flags, `n` starts over, `d` picks the level",
            "The first click is always safe; beginner, intermediate and expert, each with a best time",
            "Leave at any point and the game waits, across restarts; `t` hides the clock",
            "A daily board, the same mines for everyone that day (`Y`); signed in to pal, your record and best times follow you, and wins go on leaderboards: the day's fastest and the fastest at each level"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-board.png",
              "caption": "Mid-game on beginner: the mine counter, the face and the clock, the best time and the won count, the keys under the board"
            },
            {
              "file": "2-won.png",
              "caption": "Cleared: the mines left are flagged, the time, a new best"
            },
            {
              "file": "3-lost.png",
              "caption": "A mine went off on intermediate: every mine shows, a wrong flag is crossed out",
              "cover": [
                492,
                314,
                456,
                224
              ]
            },
            {
              "file": "4-expert.png",
              "caption": "Expert, 30 by 16 with 99 mines, scaled to the panel; Enter on the satisfied 2 opens around it"
            }
          ],
          "actions": [
            {
              "title": "Up, Down, Left, Right",
              "description": "Move the cursor. `k`, `j`, `h`, `l` too.",
              "keys": "up, down, left, right"
            },
            {
              "title": "Open",
              "description": "On a number whose flags are all placed, opens the cells around it. A new game once the game is over.",
              "keys": "enter"
            },
            {
              "title": "Flag",
              "description": "Or unflag. `f` and `space` too.",
              "keys": "/"
            },
            {
              "title": "New game",
              "description": "A fresh board; asks first mid-game. A click on the face starts one at once.",
              "keys": "n"
            },
            {
              "title": "Daily board",
              "description": "Intermediate, the same mines for everyone until midnight UTC; the first open is the middle. A win goes on the day's board. Asks first mid-game.",
              "keys": "y"
            },
            {
              "title": "Difficulty",
              "description": "The level picker: left and right choose, Enter takes it (asking first mid-game), D again closes it.",
              "keys": "d"
            },
            {
              "title": "Hide the clock",
              "description": "No running time on screen; again to bring it back. Times still count.",
              "keys": "t"
            }
          ],
          "play": true
        },
        "palettes": {
          "minesweeper": {
            "title": "Minesweeper",
            "kind": "view",
            "description": "The board, the extension's own page. Escape leaves mid-game; the board and the clock wait for you.",
            "keys": [
              {
                "keys": "up",
                "title": "Move (also down, left, right, and hjkl)"
              },
              {
                "keys": "enter",
                "title": "Open; on a satisfied number, open around it; a new game once the game is over"
              },
              {
                "keys": "/",
                "title": "Flag or unflag (also f, space)"
              },
              {
                "keys": "n",
                "title": "New game, asking first mid-game"
              },
              {
                "keys": "y",
                "title": "The daily board, asking first mid-game"
              },
              {
                "keys": "d",
                "title": "Pick the level (left, right, Enter)"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/minesweeper",
      "tagline": "Classic Minesweeper, by mouse or one hand on the arrows",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/1-board-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/1-board.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/2-won-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/2-won.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/3-lost-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/3-lost.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/4-expert-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/4-expert.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/1-board.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/2-won.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/3-lost.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/4-expert.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/1-board-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/2-won-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/3-lost-dark.png",
        "https://pal.cagdas.io/extensions/minesweeper/screenshots/4-expert-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "network",
      "kind": "bundled",
      "title": "Network",
      "description": "Every address this machine has: each interface's IPs, the public IP with its location, the gateway, the DNS servers and the Tailscale IP. Enter copies the value.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰌗",
          "bg": "cyan"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/network@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/network",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "network",
        "title": "Network",
        "description": "Every address this machine has: each interface's IPs, the public IP with its location, the gateway, the DNS servers and the Tailscale IP. Enter copies the value.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰌗",
            "bg": "cyan"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "public_ip_url",
            "label": "Public IP endpoint",
            "description": "Fetched with a 3 s timeout and kept 10 minutes; JSON with `ip` (and `city`, `country`, `org` when it has them) or a bare address. Empty: no public IP row.",
            "placeholder": "https://ipinfo.io/json",
            "default": "https://ipinfo.io/json"
          },
          {
            "kind": "list",
            "id": "networks",
            "label": "Known networks",
            "description": "One line per network, `SSID = kind label:Name icon:X`, keyed on the SSID or on the gateway (`192.168.1.1 = ...` also covers a cable into the same router and a Wi-Fi name macOS declines to reveal). Every field is optional and the order is free: a bare word is the kind, `label:` renames the network on the bar (the palette keeps the real SSID; a name with a space goes in quotes, `label:\"Cafe Corner\"`), `icon:` is one emoji or a Nerd Font glyph pasted in (the Icons palette copies one) drawn instead of the signal, hotspot, open or wired mark. Keyed fields rather than positions so a line with only an icon needs no placeholders. Kinds: `hide` drops the bar item entirely, since the network you are on almost all the time can tell you nothing and its absence is the point; `hotspot` marks one that costs data; `public` one to distrust. For example `192.168.1.1 = hide icon:󰋜`, `Cafe Wifi = hotspot label:Cafe icon:☕`.",
            "placeholder": "Cafe Wifi = hotspot label:Cafe icon:☕",
            "default": []
          }
        ],
        "store": {
          "tagline": "Every IP this machine has right now, Enter copies it",
          "category": "system",
          "features": [
            "Each interface's IPv4 and IPv6, the Wi-Fi network's name, the Tailscale IPs and the hostname",
            "The public IP with its city, country and provider (from ipinfo.io by default)",
            "The default gateway and the DNS servers in the order they are asked",
            "`enter` copies the value, `cmd+enter` opens the network settings",
            "A side pane with the details: interface, SSID, signal, MAC and status"
          ],
          "permissions": [
            "network",
            "location"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-addresses.png",
              "caption": "Every address in three sections, each row with its kind's glyph, the detail pane on the Wi-Fi interface"
            },
            {
              "file": "2-public.png",
              "caption": "The public IP with where it is and whose it is"
            },
            {
              "file": "3-search.png",
              "caption": "dns at the root finds the resolvers"
            },
            {
              "file": "4-actions.png",
              "caption": "Copy the value, or open the Network settings"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the signal as a Wi-Fi glyph and the network's name, or the label you gave it",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-open.png",
              "caption": "On an open network the glyph turns into a coffee cup, so you know before you type a password",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the connection, interface, address, gateway, signal and DNS, with keys for settings and all addresses",
              "kind": "bar",
              "box": [
                410,
                64,
                840,
                620
              ]
            },
            {
              "file": "bar-popover-open.png",
              "caption": "An open café network, flagged amber as open in the popover",
              "kind": "bar",
              "box": [
                378,
                64,
                840,
                620
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the Wi-Fi glyph and the network's label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Copy",
              "description": "The row's value.",
              "keys": "enter"
            },
            {
              "title": "Open Network settings",
              "description": "System Settings on macOS; gnome-control-center, systemsettings or nm-connection-editor on Linux.",
              "keys": "cmd+enter"
            }
          ]
        },
        "palettes": {
          "network": {
            "title": "Network",
            "kind": "live",
            "ttl": 60,
            "description": "Live rows, listed again when the panel shows and the last listing is over a minute old; ⌘R lists now and fetches the public IP again.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the value"
              },
              {
                "keys": "cmd+enter",
                "title": "Open Network settings"
              }
            ]
          }
        },
        "bar": {
          "status": {
            "title": "Network status",
            "description": "The active network, as its name (or the label Known networks gives it), or with Icon only as a glyph alone: signal strength on Wi-Fi, its own mark for a hotspot or an open network, wired, or offline, or the icon Known networks gives that network (home, office, cafe, phone). A network set to `hide` there draws nothing. Click opens Network Settings; the popover names the connection and its kind, then the interface, the address, the gateway, the signal and security, and the DNS servers.",
            "refresh": {
              "every": 5,
              "on": [
                "network",
                "wake"
              ]
            },
            "mocks": {
              "wifi": {
                "title": "Named Wi-Fi",
                "item": {
                  "icon": "󰤥",
                  "title": "Cafe",
                  "tooltip": "Cafe Wifi · 192.168.1.131 · Signal 72% · Gateway 192.168.1.1 · en0"
                }
              },
              "weak": {
                "title": "Weak signal",
                "item": {
                  "icon": "󰤟",
                  "title": "Cafe",
                  "tooltip": "Cafe Wifi · 192.168.1.131 · Signal 38% · Gateway 192.168.1.1 · en0"
                }
              },
              "hotspot": {
                "title": "Phone hotspot",
                "item": {
                  "icon": "󰄜",
                  "title": "iPhone",
                  "tooltip": "iPhone · 172.20.10.3 · Signal 88% · Gateway 172.20.10.1 · en0"
                }
              },
              "open": {
                "title": "Open network",
                "item": {
                  "icon": "󰅶",
                  "title": "Cafe Guest",
                  "tooltip": "Cafe Guest · 10.0.1.44 · Signal 61% · Gateway 10.0.1.1 · en0"
                }
              },
              "wired": {
                "title": "Wired",
                "item": {
                  "icon": "󰈀",
                  "title": "Ethernet",
                  "tooltip": "Ethernet · 10.0.0.7 · Gateway 10.0.0.1 · en5"
                }
              },
              "offline": {
                "title": "No route",
                "item": {
                  "icon": "󰤭",
                  "title": "Offline",
                  "color": "red",
                  "tooltip": "No route to the internet"
                }
              },
              "glyph": {
                "title": "Glyph only (show_title off on the item)",
                "item": {
                  "icon": "󰤨",
                  "tooltip": "Cafe Wifi · 192.168.1.131 · Signal 94% · Gateway 192.168.1.1 · en0"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open Network settings"
              },
              {
                "keys": "cmd+a",
                "title": "All addresses"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/network",
      "tagline": "Every IP this machine has right now, Enter copies it",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/network/screenshots/1-addresses-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/1-addresses.png",
        "https://pal.cagdas.io/extensions/network/screenshots/2-public-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/2-public.png",
        "https://pal.cagdas.io/extensions/network/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/network/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar-open-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar-open.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover-open-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover-open.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/network/screenshots/1-addresses.png",
        "https://pal.cagdas.io/extensions/network/screenshots/2-public.png",
        "https://pal.cagdas.io/extensions/network/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/network/screenshots/4-actions.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar-open.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover-open.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/network/screenshots/1-addresses-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/2-public-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/4-actions-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar-open-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover-open-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/network/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "status",
          "title": "Network status",
          "description": "The active network, as its name (or the label Known networks gives it), or with Icon only as a glyph alone: signal strength on Wi-Fi, its own mark for a hotspot or an open network, wired, or offline, or the icon Known networks gives that network (home, office, cafe, phone). A network set to `hide` there draws nothing. Click opens Network Settings; the popover names the connection and its kind, then the interface, the address, the gateway, the signal and security, and the DNS servers.",
          "refresh": {
            "every": 5,
            "on": [
              "network",
              "wake"
            ]
          },
          "refresh_words": "every 5s, when the network is back, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "night-parade",
      "kind": "registry",
      "title": "Night Parade",
      "description": "A survivors game: the Night Parade of One Hundred Demons marches through an abandoned village tonight, and you last until dawn. Six heroes, sixteen weapons that evolve, sixteen items, a fifteen-minute night in three acts with six bosses, a shrine for lasting upgrades, unlocks and harder omens. Built on the Ninja Adventure pack (CC0).",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M6 1h4v1.5H6zM4.5 2.5h7v1h-7zM3.5 3.5h9v7h-9zM4.5 10.5h7v1h-7zM6 11.5h4v1.5H6zM7.5 13h1v2.5h-1z",
          "bg": "red"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/night-parade@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/night-parade",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "night-parade",
        "title": "Night Parade",
        "description": "A survivors game: the Night Parade of One Hundred Demons marches through an abandoned village tonight, and you last until dawn. Six heroes, sixteen weapons that evolve, sixteen items, a fifteen-minute night in three acts with six bosses, a shrine for lasting upgrades, unlocks and harder omens. Built on the Ninja Adventure pack (CC0).",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M6 1h4v1.5H6zM4.5 2.5h7v1h-7zM3.5 3.5h9v7h-9zM4.5 10.5h7v1h-7zM6 11.5h4v1.5H6zM7.5 13h1v2.5h-1z",
            "bg": "red"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "id": "volume",
            "label": "Volume",
            "kind": "number",
            "description": "How loud the whole game is; music and sound keep their own balance in the game's settings.",
            "min": 0,
            "max": 100,
            "step": 5,
            "unit": "%",
            "slider": true,
            "default": 100
          }
        ],
        "sync": {
          "save": {
            "fields": {
              "v": "max",
              "gold": "sum",
              "shrine": {
                "fields": {
                  "might": "max",
                  "armor": "max",
                  "maxHp": "max",
                  "recovery": "max",
                  "cooldown": "max",
                  "area": "max",
                  "speed": "max",
                  "duration": "max",
                  "amount": "max",
                  "move": "max",
                  "magnet": "max",
                  "luck": "max",
                  "growth": "max",
                  "greed": "max",
                  "revival": "max",
                  "reroll": "max",
                  "skip": "max",
                  "banish": "max"
                }
              },
              "spent": "sum",
              "unlocked": "union",
              "hero": "latest",
              "omen": "latest",
              "seen": {
                "fields": {
                  "weapons": "union",
                  "items": "union",
                  "evolved": "union",
                  "enemies": {
                    "fields": {
                      "slime": "sum",
                      "slimelet": "sum",
                      "bat": "sum",
                      "larva": "sum",
                      "mushroom": "sum",
                      "snake": "sum",
                      "mole": "sum",
                      "tanuki": "sum",
                      "kappa": "sum",
                      "lantern": "sum",
                      "skull": "sum",
                      "owl": "sum",
                      "spirit": "sum",
                      "skeleton": "sum",
                      "eye": "sum",
                      "octopus": "sum",
                      "bamboo": "sum",
                      "cyclops": "sum",
                      "imp": "sum",
                      "onibi": "sum",
                      "beast": "sum",
                      "dragon": "sum",
                      "panda": "sum",
                      "crow": "sum",
                      "goldtanuki": "sum"
                    }
                  },
                  "bosses": {
                    "fields": {
                      "frog": "sum",
                      "tanuki": "sum",
                      "yurei": "sum",
                      "tengu": "sum",
                      "samurai": "sum",
                      "oni": "sum"
                    }
                  }
                }
              },
              "best": {
                "fields": {
                  "kaze": {
                    "fields": {
                      "t": "max",
                      "dawn": "max",
                      "level": "max",
                      "kills": "max"
                    }
                  },
                  "tomoe": {
                    "fields": {
                      "t": "max",
                      "dawn": "max",
                      "level": "max",
                      "kills": "max"
                    }
                  },
                  "seimei": {
                    "fields": {
                      "t": "max",
                      "dawn": "max",
                      "level": "max",
                      "kills": "max"
                    }
                  },
                  "ennen": {
                    "fields": {
                      "t": "max",
                      "dawn": "max",
                      "level": "max",
                      "kills": "max"
                    }
                  },
                  "raiden": {
                    "fields": {
                      "t": "max",
                      "dawn": "max",
                      "level": "max",
                      "kills": "max"
                    }
                  },
                  "hayate": {
                    "fields": {
                      "t": "max",
                      "dawn": "max",
                      "level": "max",
                      "kills": "max"
                    }
                  }
                }
              },
              "totals": {
                "fields": {
                  "nights": "sum",
                  "dawns": "sum",
                  "kills": "sum",
                  "gold": "sum"
                }
              },
              "settings": {
                "fields": {
                  "music": "latest",
                  "sfx": "latest",
                  "numbers": "latest",
                  "shake": "latest"
                }
              }
            }
          },
          "run": "local",
          "scene": "local"
        },
        "leaderboards": [
          {
            "id": "night/kaze",
            "title": "Kaze: longest night",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 900
          },
          {
            "id": "night/tomoe",
            "title": "Tomoe: longest night",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 900
          },
          {
            "id": "night/seimei",
            "title": "Seimei: longest night",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 900
          },
          {
            "id": "night/ennen",
            "title": "Ennen: longest night",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 900
          },
          {
            "id": "night/raiden",
            "title": "Raiden: longest night",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 900
          },
          {
            "id": "night/hayate",
            "title": "Hayate: longest night",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 900
          },
          {
            "id": "dawn",
            "title": "Fastest dawn",
            "order": "asc",
            "format": "time",
            "min": 900,
            "max": 3600
          },
          {
            "id": "kills",
            "title": "Most defeated in a night",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 1000000
          }
        ],
        "store": {
          "tagline": "Last the night against the parade of a hundred demons",
          "category": "fun",
          "play": true,
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Move",
              "description": "WASD too.",
              "keys": "up, down, left, right"
            },
            {
              "title": "Smoke dash",
              "description": "A short burst you can't be hurt in.",
              "keys": "space"
            },
            {
              "title": "Pick at a level-up",
              "description": "Or the arrows and Enter; R rerolls, X skips, B banishes.",
              "keys": "1, 2, 3"
            },
            {
              "title": "Pause",
              "description": "Your build and stats; Q gives up the night.",
              "keys": "esc"
            },
            {
              "title": "Sound on or off",
              "keys": "m"
            }
          ],
          "features": [
            "A fifteen-minute night in three acts (Dusk, Midnight, the Hour of the Ox), each with its own crowd, scripted events and a boss: the Tanuki, the Tengu, and the Oni at the head of the parade",
            "Sixteen weapons, each with its own job, eight levels and an evolution when paired with the right item; sixteen items; reroll, skip and banish at level-ups",
            "Six heroes with a starting weapon and a trait, four of them unlocked by playing",
            "Telegraphed danger: rings and lines on the ground before a slam or a charge, a smoke dash to get out",
            "A blessing to choose as Midnight and the Hour of the Ox begin: more damage, more projectiles, more area, armor, healing or speed for the rest of the night",
            "A shrine for lasting upgrades between nights, a codex of everything found and defeated, and omens for harder nights once you've seen the dawn",
            "Leaderboards for each hero's longest night, the fastest dawn and the most demons defeated; signed in, your gold, shrine, unlocks and codex follow you to your other machines and play.cagdas.io"
          ],
          "screenshots": [
            {
              "file": "1-night.png",
              "caption": "Midnight, 8:06 into the night: shuriken, katana, thunder, fire talisman and spirit wisps against the Act II crowd"
            },
            {
              "file": "2-tengu.png",
              "caption": "10:10, the Tengu arrives; Storm of Stars and Crescent Moon already evolved",
              "cover": [
                241,
                294,
                958,
                470
              ]
            },
            {
              "file": "3-levelup.png",
              "caption": "A level-up: three choices with what each adds, the item that evolves a weapon you carry starred"
            },
            {
              "file": "4-evolve.png",
              "caption": "A golden chest: the shuriken with its Scroll evolves into Storm of Stars, and four more upgrades"
            },
            {
              "file": "5-title.png",
              "caption": "The title, with a night playing behind it"
            },
            {
              "file": "6-heroes.png",
              "caption": "Who walks tonight: six heroes, each with a starting weapon and a trait; four open up by playing"
            }
          ]
        },
        "palettes": {
          "night-parade": {
            "title": "Night Parade",
            "kind": "view",
            "description": "A night against the parade. Escape or closing the panel pauses it, and it waits there for you.",
            "keys": [
              {
                "keys": "up",
                "title": "Move (arrows or WASD)"
              },
              {
                "keys": "space",
                "title": "Smoke dash"
              },
              {
                "keys": "1",
                "title": "Pick at a level-up (R reroll, X skip, B banish)"
              },
              {
                "keys": "esc",
                "title": "Pause: your build and stats"
              },
              {
                "keys": "s",
                "title": "Settings, while paused"
              },
              {
                "keys": "m",
                "title": "Sound on or off"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/night-parade",
      "tagline": "Last the night against the parade of a hundred demons",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/night-parade/screenshots/1-night-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/1-night.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/2-tengu-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/2-tengu.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/3-levelup-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/3-levelup.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/4-evolve-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/4-evolve.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/5-title-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/5-title.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/6-heroes-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/6-heroes.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/night-parade/screenshots/1-night.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/2-tengu.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/3-levelup.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/4-evolve.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/5-title.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/6-heroes.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/night-parade/screenshots/1-night-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/2-tengu-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/3-levelup-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/4-evolve-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/5-title-dark.png",
        "https://pal.cagdas.io/extensions/night-parade/screenshots/6-heroes-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "obsidian",
      "kind": "registry",
      "title": "Obsidian",
      "description": "Your Obsidian vault in the panel: find any note by title, search the full text, append to today's daily note and start new notes from a template. Notes open in Obsidian or your editor, or read right in the panel.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M19.355 18.538a68.967 68.959 0 0 0 1.858-2.954.81.81 0 0 0-.062-.9c-.516-.685-1.504-2.075-2.042-3.362-.553-1.321-.636-3.375-.64-4.377a1.707 1.707 0 0 0-.358-1.05l-3.198-4.064a3.744 3.744 0 0 1-.076.543c-.106.503-.307 1.004-.536 1.5-.134.29-.29.6-.446.914l-.31.626c-.516 1.068-.997 2.227-1.132 3.59-.124 1.26.046 2.73.815 4.481.128.011.257.025.386.044a6.363 6.363 0 0 1 3.326 1.505c.916.79 1.744 1.922 2.415 3.5zM8.199 22.569c.073.012.146.02.22.02.78.024 2.095.092 3.16.29.87.16 2.593.64 4.01 1.055 1.083.316 2.198-.548 2.355-1.664.114-.814.33-1.735.725-2.58l-.01.005c-.67-1.87-1.522-3.078-2.416-3.849a5.295 5.295 0 0 0-2.778-1.257c-1.54-.216-2.952.19-3.84.45.532 2.218.368 4.829-1.425 7.531zM5.533 9.938c-.023.1-.056.197-.098.29L2.82 16.059a1.602 1.602 0 0 0 .313 1.772l4.116 4.24c2.103-3.101 1.796-6.02.836-8.3-.728-1.73-1.832-3.081-2.55-3.831zM9.32 14.01c.615-.183 1.606-.465 2.745-.534-.683-1.725-.848-3.233-.716-4.577.154-1.552.7-2.847 1.235-3.95.113-.235.223-.454.328-.664.149-.297.288-.577.419-.86.217-.47.379-.885.46-1.27.08-.38.08-.72-.014-1.043-.095-.325-.297-.675-.68-1.06a1.6 1.6 0 0 0-1.475.36l-4.95 4.452a1.602 1.602 0 0 0-.513.952l-.427 2.83c.672.59 2.328 2.316 3.335 4.711.09.21.175.43.253.653z",
          "box": 24,
          "bg": "#7C3AED"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/obsidian@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/obsidian",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "obsidian",
        "title": "Obsidian",
        "description": "Your Obsidian vault in the panel: find any note by title, search the full text, append to today's daily note and start new notes from a template. Notes open in Obsidian or your editor, or read right in the panel.",
        "keywords": [
          "vault",
          "wiki"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M19.355 18.538a68.967 68.959 0 0 0 1.858-2.954.81.81 0 0 0-.062-.9c-.516-.685-1.504-2.075-2.042-3.362-.553-1.321-.636-3.375-.64-4.377a1.707 1.707 0 0 0-.358-1.05l-3.198-4.064a3.744 3.744 0 0 1-.076.543c-.106.503-.307 1.004-.536 1.5-.134.29-.29.6-.446.914l-.31.626c-.516 1.068-.997 2.227-1.132 3.59-.124 1.26.046 2.73.815 4.481.128.011.257.025.386.044a6.363 6.363 0 0 1 3.326 1.505c.916.79 1.744 1.922 2.415 3.5zM8.199 22.569c.073.012.146.02.22.02.78.024 2.095.092 3.16.29.87.16 2.593.64 4.01 1.055 1.083.316 2.198-.548 2.355-1.664.114-.814.33-1.735.725-2.58l-.01.005c-.67-1.87-1.522-3.078-2.416-3.849a5.295 5.295 0 0 0-2.778-1.257c-1.54-.216-2.952.19-3.84.45.532 2.218.368 4.829-1.425 7.531zM5.533 9.938c-.023.1-.056.197-.098.29L2.82 16.059a1.602 1.602 0 0 0 .313 1.772l4.116 4.24c2.103-3.101 1.796-6.02.836-8.3-.728-1.73-1.832-3.081-2.55-3.831zM9.32 14.01c.615-.183 1.606-.465 2.745-.534-.683-1.725-.848-3.233-.716-4.577.154-1.552.7-2.847 1.235-3.95.113-.235.223-.454.328-.664.149-.297.288-.577.419-.86.217-.47.379-.885.46-1.27.08-.38.08-.72-.014-1.043-.095-.325-.297-.675-.68-1.06a1.6 1.6 0 0 0-1.475.36l-4.95 4.452a1.602 1.602 0 0 0-.513.952l-.427 2.83c.672.59 2.328 2.316 3.335 4.711.09.21.175.43.253.653z",
            "box": 24,
            "bg": "#7C3AED"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "vault",
            "label": "Vault",
            "description": "The vault folder. Empty takes the vault Obsidian has open, or opened last (obsidian.json).",
            "pick": "folder",
            "placeholder": "~/Sync/vault",
            "default": ""
          },
          {
            "kind": "select",
            "id": "open_with",
            "label": "Open with",
            "description": "What Enter does on a note; cmd+Enter is the other one.",
            "options": [
              {
                "id": "obsidian",
                "title": "Obsidian"
              },
              {
                "id": "editor",
                "title": "The editor"
              }
            ],
            "default": "obsidian"
          },
          {
            "kind": "text",
            "id": "editor",
            "label": "Editor",
            "description": "The command Open in editor runs with the file's path last (code, subl, zed). Empty opens the file with whatever the OS opens .md files with.",
            "placeholder": "code",
            "default": ""
          },
          {
            "kind": "text",
            "id": "daily_folder",
            "label": "Daily notes folder",
            "description": "Where daily notes live, relative to the vault. Empty reads Obsidian's daily-notes plugin (.obsidian/daily-notes.json).",
            "placeholder": "daily",
            "default": ""
          },
          {
            "kind": "text",
            "id": "daily_format",
            "label": "Daily note name",
            "description": "The date format of a daily note's name, moment's tokens as Obsidian takes them. Empty reads the plugin; YYYY-MM-DD when it says nothing.",
            "placeholder": "YYYY-MM-DD",
            "default": ""
          },
          {
            "kind": "text",
            "id": "daily_template",
            "label": "Daily note template",
            "description": "The note a new daily note starts as, relative to the vault ({{date}}, {{time}}, {{title}} filled). Empty reads the plugin.",
            "placeholder": "templates/daily",
            "default": ""
          },
          {
            "kind": "text",
            "id": "template",
            "label": "New note template",
            "description": "The note New note starts as, relative to the vault ({{title}}, {{date}}, {{time}} filled). Empty starts from your selection or the clipboard.",
            "placeholder": "templates/note",
            "default": ""
          },
          {
            "kind": "list",
            "id": "exclude",
            "label": "Exclude",
            "description": "Folders and files left out of every palette, as globs relative to the vault. Dot folders (.obsidian, .trash) are always out.",
            "placeholder": "templates/**",
            "default": []
          }
        ],
        "store": {
          "tagline": "Find, search and add to your Obsidian notes",
          "category": "productivity",
          "features": [
            "Every note at the root by title, alias, tag or folder; `enter` opens it in Obsidian, `cmd+enter` in your editor",
            "Full-text search across the vault as you type, the matching line under each note",
            "Today's daily note, created from its template if missing; Append to today adds a line",
            "New notes from a template; tags, recent notes, backlinks and outgoing links",
            "Read a note in the panel with its headings, callouts, code and tables (`cmd+shift+r`)",
            "`cmd+c` copies a `[[wikilink]]`; the list stays in step with the vault on disk"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-notes.png",
              "caption": "Notes: every note by title, sectioned by folder, tags and the change date on the row"
            },
            {
              "file": "2-detail.png",
              "caption": "The pane: the vault and folder over the title, its tags, words, backlinks and links, then the note rendered, callout and table included"
            },
            {
              "file": "3-search.png",
              "caption": "Search Notes: the matching line on each row, the matches bold in the pane"
            },
            {
              "file": "4-daily.png",
              "caption": "Daily Notes: today, yesterday, this week, Append to today, New note"
            },
            {
              "file": "5-append.png",
              "caption": "Append to today: one line, the clipboard already in it, lands at the end of today's note"
            },
            {
              "file": "6-read.png",
              "caption": "A note read in pal: callouts, lists, code and tables drawn with the tokens"
            }
          ],
          "actions": [
            {
              "title": "Open in Obsidian",
              "description": "The note in Obsidian, through obsidian://open; first or second per the Open with setting.",
              "keys": "enter"
            },
            {
              "title": "Open in editor",
              "description": "The editor command with the file's path; the OS opener without one.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy wikilink",
              "description": "[[name]], or [[folder/name]] when another note shares the name.",
              "keys": "cmd+c"
            },
            {
              "title": "Read in pal",
              "description": "The note drawn in the panel.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Backlinks",
              "description": "The notes that link to it.",
              "keys": "cmd+b"
            },
            {
              "title": "Outgoing links",
              "description": "The notes it links to; a link to nothing yet offers Create the note.",
              "keys": "cmd+l"
            },
            {
              "title": "Copy path",
              "description": "The file's absolute path.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Append a line",
              "description": "The line typed in the bar (the note row's argument) lands at the end of the note, placeholders filled; a form when picked without it.",
              "keys": "cmd+shift+a"
            },
            {
              "title": "Create today's note",
              "description": "From the daily template; asks first.",
              "keys": "enter"
            },
            {
              "title": "Append to today",
              "description": "The line typed in the bar lands on its own line at the end of today's note; from Today's note's cmd+enter, a form.",
              "keys": "enter"
            },
            {
              "title": "New note",
              "description": "The title and the folder typed in the bar; the body from the template or your selection.",
              "keys": "enter"
            },
            {
              "title": "Notes with the tag",
              "description": "On a tag row: the notes carrying it.",
              "keys": "enter"
            },
            {
              "title": "Search in Obsidian",
              "description": "On the Search notes command: Obsidian's own search.",
              "keys": "cmd+enter"
            }
          ]
        },
        "links": {
          "open": {
            "description": "Open a note in Obsidian or the editor",
            "params": {
              "path": {
                "description": "The note's path in the vault (with or without .md) or its name as a wikilink says it",
                "required": true
              }
            }
          },
          "new": {
            "description": "Create a note and open it",
            "params": {
              "title": {
                "description": "The title, also the file name",
                "required": true
              },
              "body": {
                "description": "The markdown body; {{title}} and {{date}} are filled"
              },
              "folder": {
                "description": "A folder of the vault; the top when empty"
              }
            }
          },
          "append-today": {
            "description": "Append a line to today's daily note, created when missing",
            "params": {
              "text": {
                "description": "The line; {selection}, {clipboard}, {date} and {time} are filled",
                "required": true
              }
            }
          }
        },
        "palettes": {
          "notes": {
            "title": "Notes",
            "description": "Every note of the vault by title, alias, tag or folder, sectioned by folder; Today's note, New note (the title and the folder typed in the bar), Search notes and Random note at the top.",
            "kind": "list",
            "tier": "primary",
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Obsidian (or the editor, per the setting)"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in the editor (or Obsidian)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the wikilink"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Read the note in pal"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the note"
              },
              {
                "keys": "cmd+l",
                "title": "What the note links to"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Append the line typed in the bar"
              }
            ]
          },
          "search": {
            "title": "Search Notes",
            "description": "Full-text over every note as you type: ripgrep when on PATH, a one-second scan otherwise; the matching line on the row, the matches bold in the pane.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Obsidian (or the editor, per the setting)"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in the editor (or Obsidian)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the wikilink"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Read the note in pal"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the note"
              },
              {
                "keys": "cmd+l",
                "title": "What the note links to"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Append the line typed in the bar"
              }
            ]
          },
          "daily": {
            "title": "Daily Notes",
            "description": "Today's note (created from the template when missing), yesterday's, this week's; Append to today and New note, their values typed in the bar.",
            "kind": "live",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the note; on Create today's note, create it (asks first); on Append to today and New note, with the line, or the title and folder, typed in the bar's fields"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in the editor (or Obsidian)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the wikilink"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Read the note in pal"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the note"
              },
              {
                "keys": "cmd+l",
                "title": "What the note links to"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Append the line typed in the bar"
              }
            ]
          },
          "tags": {
            "title": "Tags",
            "description": "Every tag in the vault with how many notes carry it; Enter lists them.",
            "kind": "list",
            "tier": "catalog",
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "The notes with the tag"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the tag"
              }
            ]
          },
          "recent": {
            "title": "Recent Notes",
            "description": "The twenty notes changed last, newest first.",
            "kind": "live",
            "remember": false,
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Obsidian (or the editor, per the setting)"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in the editor (or Obsidian)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the wikilink"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Read the note in pal"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the note"
              },
              {
                "keys": "cmd+l",
                "title": "What the note links to"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Append the line typed in the bar"
              }
            ]
          },
          "backlinks": {
            "title": "Backlinks",
            "description": "The notes that link to the note you opened last, or to the row cmd+b came from.",
            "kind": "list",
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the linking note"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in the editor (or Obsidian)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the wikilink"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Read the note in pal"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the note"
              },
              {
                "keys": "cmd+l",
                "title": "What the note links to"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Append the line typed in the bar"
              }
            ]
          },
          "outgoing": {
            "title": "Outgoing Links",
            "description": "The notes the note you opened last links to, or the row cmd+l came from; a link to nothing yet offers Create the note.",
            "kind": "list",
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the linked note; on a link to nothing, create it"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in the editor (or Obsidian)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the wikilink"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Read the note in pal"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the note"
              },
              {
                "keys": "cmd+l",
                "title": "What the note links to"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Append the line typed in the bar"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/obsidian",
      "tagline": "Find, search and add to your Obsidian notes",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/obsidian/screenshots/1-notes-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/1-notes.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/4-daily-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/4-daily.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/5-append-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/5-append.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/6-read-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/6-read.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/obsidian/screenshots/1-notes.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/3-search.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/4-daily.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/5-append.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/6-read.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/obsidian/screenshots/1-notes-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/3-search-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/4-daily-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/5-append-dark.png",
        "https://pal.cagdas.io/extensions/obsidian/screenshots/6-read-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "open",
          "url": "pal://obsidian/open?path=\u003cpath\u003e",
          "cli": "pal call obsidian/open path=\u003cpath\u003e",
          "description": "Open a note in Obsidian or the editor",
          "params": [
            {
              "name": "path",
              "description": "The note's path in the vault (with or without .md) or its name as a wikilink says it",
              "required": true
            }
          ]
        },
        {
          "route": "new",
          "url": "pal://obsidian/new?title=\u003ctitle\u003e",
          "cli": "pal call obsidian/new title=\u003ctitle\u003e",
          "description": "Create a note and open it",
          "params": [
            {
              "name": "title",
              "description": "The title, also the file name",
              "required": true
            },
            {
              "name": "body",
              "description": "The markdown body; {{title}} and {{date}} are filled"
            },
            {
              "name": "folder",
              "description": "A folder of the vault; the top when empty"
            }
          ]
        },
        {
          "route": "append-today",
          "url": "pal://obsidian/append-today?text=\u003ctext\u003e",
          "cli": "pal call obsidian/append-today text=\u003ctext\u003e",
          "description": "Append a line to today's daily note, created when missing",
          "params": [
            {
              "name": "text",
              "description": "The line; {selection}, {clipboard}, {date} and {time} are filled",
              "required": true
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "odak",
      "kind": "registry",
      "title": "odak",
      "description": "Your odak todos in the panel: open ones by section with today's and the overdue on top, a new todo in one typed line, search across open and done, and today's count on the bar.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰄴",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/odak@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/odak",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "odak",
        "title": "odak",
        "description": "Your odak todos in the panel: open ones by section with today's and the overdue on top, a new todo in one typed line, search across open and done, and today's count on the bar.",
        "keywords": [
          "todo",
          "todos",
          "task",
          "tasks"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰄴",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "text",
            "id": "url",
            "required": true,
            "label": "Address",
            "description": "The odak server: http://host:8761 on your network, or its public address.",
            "placeholder": "http://host:8761",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "api_key",
            "required": true,
            "label": "API key",
            "description": "The server's ODAK_API_KEY.",
            "placeholder": "the key",
            "default": ""
          },
          {
            "kind": "text",
            "id": "default_section",
            "label": "Section for new todos",
            "description": "Where a todo lands unless the line names one with /section.",
            "placeholder": "Inbox",
            "default": "Inbox"
          }
        ],
        "palettes": {
          "odak": {
            "title": "Todos",
            "description": "Every open todo: the overdue and today's first, then the file's sections in order, subtasks under their parent, what waits for a day at the end. Add a todo from the first row, typed in the bar.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keys": [
              {
                "keys": "enter",
                "title": "Complete (Tab marks several)"
              },
              {
                "keys": "cmd+e",
                "title": "Edit: text, section, tags, due day, urgent"
              },
              {
                "keys": "cmd+t",
                "title": "Snooze to tomorrow"
              },
              {
                "keys": "cmd+s",
                "title": "Snooze: tomorrow, in 3 days, next Monday, next week, a day typed"
              },
              {
                "keys": "cmd+m",
                "title": "Move to a section"
              },
              {
                "keys": "cmd+u",
                "title": "Mark urgent, or not"
              },
              {
                "keys": "cmd+n",
                "title": "Add a subtask"
              },
              {
                "keys": "cmd+l",
                "title": "Open the link in the todo"
              },
              {
                "keys": "cmd+o",
                "title": "Open odak"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the text"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the link (the todo's, else odak's)"
              },
              {
                "keys": "cmd+d",
                "title": "Delete (asks; subtasks go with it)"
              }
            ]
          },
          "add": {
            "title": "Add Todo",
            "description": "A todo typed in one line: #tag, ! for urgent, /section, d:day or a day in words at the end (tomorrow, fri, next mon, in 3 days, 20 sep); the row reads it back as you type, Enter adds it. Before you type: the selected text and the clipboard as todos.",
            "kind": "input",
            "fallback": "Add “{query}” to odak",
            "keys": [
              {
                "keys": "enter",
                "title": "Add"
              },
              {
                "keys": "cmd+enter",
                "title": "Add and type another"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the line"
              }
            ]
          },
          "search": {
            "title": "Search Todos",
            "description": "Every word typed against the text, tags and section of every todo, open and completed; a completed one reopens on Enter.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Complete an open todo; reopen a completed one"
              },
              {
                "keys": "cmd+e",
                "title": "Edit"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the text"
              },
              {
                "keys": "cmd+d",
                "title": "Delete (asks)"
              }
            ]
          },
          "done": {
            "title": "Completed",
            "description": "What is checked off, by section, the ones completed from pal with when; Enter reopens.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keys": [
              {
                "keys": "enter",
                "title": "Reopen (Tab marks several)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the text"
              },
              {
                "keys": "cmd+o",
                "title": "Open odak"
              },
              {
                "keys": "cmd+d",
                "title": "Delete (asks; Tab marks several)"
              }
            ]
          }
        },
        "bar": {
          "today": {
            "title": "Today",
            "description": "How many todos are due today or sit in today's sections, red while any is overdue, hidden at zero; the popover lists them with a cursor, completes on Enter and adds from a field.",
            "refresh": {
              "every": 300,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "settings": [
              {
                "kind": "list",
                "id": "today_sections",
                "label": "Today's sections",
                "description": "Sections the item counts as today's work, on top of what is due today.",
                "placeholder": "Focus",
                "default": [
                  "Focus",
                  "Today"
                ]
              }
            ],
            "mocks": {
              "busy": {
                "title": "Three today, none overdue",
                "item": {
                  "icon": "󰄴",
                  "title": "3",
                  "tooltip": "3 today"
                }
              },
              "overdue": {
                "title": "One overdue (red by its rule)",
                "item": {
                  "icon": "󰄴",
                  "title": "4",
                  "color": "red",
                  "tooltip": "1 overdue, 3 today"
                }
              },
              "clear": {
                "title": "Nothing due today",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰄴",
                    "tooltip": "Nothing due today"
                  }
                }
              },
              "out": {
                "title": "Signed out",
                "item": {
                  "hidden": true
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Complete the focused todo (x too)"
              },
              {
                "keys": "u",
                "title": "Mark the focused todo urgent, or not"
              },
              {
                "keys": "t",
                "title": "Snooze the focused todo to tomorrow"
              },
              {
                "keys": "n",
                "title": "A field: type a todo, Enter adds it"
              },
              {
                "keys": "o",
                "title": "Open odak"
              },
              {
                "keys": "p",
                "title": "Open the Todos palette"
              },
              {
                "keys": "r",
                "title": "Fetch again"
              },
              {
                "keys": "up, down",
                "title": "Move between the rows (j, k too; a click sets the cursor)"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "odak.today == 0 and odak.overdue == 0",
                "description": "Nothing due today and nothing in today's sections: off the strip, muted for anyone who keeps it.",
                "hidden": true,
                "color": "muted"
              },
              {
                "id": "overdue",
                "when": "odak.overdue \u003e 0",
                "description": "Something is past its day.",
                "color": "red"
              }
            ]
          }
        },
        "states": {
          "overdue": {
            "description": "Open todos past their day",
            "kind": "number"
          },
          "today": {
            "description": "Open todos due today or in today's sections (overdue ones aside)",
            "kind": "number"
          },
          "open": {
            "description": "Open todos in all",
            "kind": "number"
          }
        },
        "links": {
          "add": {
            "description": "Add a todo; the text takes the add line's grammar (#tag, !, /section, a day at the end)",
            "params": {
              "text": {
                "description": "The todo",
                "required": true
              },
              "section": {
                "description": "The section; the setting's default otherwise"
              },
              "due": {
                "description": "A day: tomorrow, fri, next mon, in 3 days, 2026-10-01"
              },
              "tags": {
                "description": "Tags, repeated",
                "type": "string[]"
              },
              "urgent": {
                "description": "Flag it",
                "type": "boolean"
              }
            }
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Your odak todos: add in one line, see today's on the bar",
          "category": "productivity",
          "features": [
            "Todos by section, overdue and today's on top; `enter` completes, with Undo right after",
            "Add in one line: `#tag`, `!` for urgent, `/section` and a day in words (`tomorrow`, `fri`, `in 3 days`)",
            "Snooze, move between sections, or edit everything in a form",
            "Search across open and completed todos, and reopen what you checked off",
            "Today's count on the bar, red when anything is overdue; add and complete from its popover",
            "`pal://odak/add?text=...` adds a todo from a script or a keybind"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-todos.png",
              "caption": "Every todo by section, the overdue and today's on top, a subtask under its parent; Enter completes"
            },
            {
              "file": "2-add.png",
              "caption": "One line adds a todo: #tag, ! for urgent and a day in words, read back as you type"
            },
            {
              "file": "3-snooze.png",
              "caption": "Snooze to tomorrow, next Monday or a day typed in words"
            },
            {
              "file": "4-search.png",
              "caption": "Search reaches open and completed todos alike, by text or by tag"
            },
            {
              "file": "5-edit.png",
              "caption": "Edit everything in one form: the text, the section, the tags and the day"
            },
            {
              "file": "6-completed.png",
              "caption": "Completed lists what is checked off; Enter reopens one"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: today's count, red while anything is overdue",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the overdue first, then today's, Enter completes, n adds",
              "kind": "bar",
              "box": [
                438,
                64,
                840,
                686
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the glyph and the count, red for the overdue one",
              "kind": "bar"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/odak",
      "tagline": "Your odak todos: add in one line, see today's on the bar",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/odak/screenshots/1-todos-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/1-todos.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/2-add-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/2-add.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/3-snooze-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/3-snooze.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/4-search-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/4-search.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/5-edit-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/5-edit.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/6-completed-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/6-completed.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/odak/screenshots/1-todos.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/2-add.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/3-snooze.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/4-search.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/5-edit.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/6-completed.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/odak/screenshots/1-todos-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/2-add-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/3-snooze-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/4-search-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/5-edit-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/6-completed-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/odak/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "today",
          "title": "Today",
          "description": "How many todos are due today or sit in today's sections, red while any is overdue, hidden at zero; the popover lists them with a cursor, completes on Enter and adds from a field.",
          "refresh": {
            "every": 300,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "add",
          "url": "pal://odak/add?text=\u003ctext\u003e",
          "cli": "pal call odak/add text=\u003ctext\u003e",
          "description": "Add a todo; the text takes the add line's grammar (#tag, !, /section, a day at the end)",
          "params": [
            {
              "name": "text",
              "description": "The todo",
              "required": true
            },
            {
              "name": "section",
              "description": "The section; the setting's default otherwise"
            },
            {
              "name": "due",
              "description": "A day: tomorrow, fri, next mon, in 3 days, 2026-10-01"
            },
            {
              "name": "tags",
              "description": "Tags, repeated",
              "type": "string[]"
            },
            {
              "name": "urgent",
              "description": "Flag it",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "onepassword",
      "kind": "registry",
      "title": "1Password",
      "description": "Your 1Password items from the keyboard, through the op command line tool. Enter copies the password; the username, the one-time code and the item in the app are one key away.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M12 0c6.627 0 12 5.373 12 12 0 6.628-5.373 12-12 12S0 18.628 0 12C0 5.373 5.373 0 12 0m-.893 4.86c-.485 0-.727.001-.913.095a.87.87 0 0 0-.378.379c-.094.185-.095.428-.095.912v2.747c0 .12 0 .182.016.238q.02.075.065.138a1 1 0 0 0 .175.162l.695.564c.113.092.17.139.19.194a.22.22 0 0 1 0 .15c-.02.056-.077.102-.19.194l-.695.564a1 1 0 0 0-.175.162.4.4 0 0 0-.065.138 1 1 0 0 0-.016.238v6.019c0 .485 0 .728.095.913a.87.87 0 0 0 .378.378c.186.094.428.094.913.094h1.786c.485 0 .727 0 .913-.094a.87.87 0 0 0 .378-.378c.095-.185.095-.428.095-.913v-2.747c0-.12 0-.182-.016-.238a.4.4 0 0 0-.065-.138 1 1 0 0 0-.175-.162l-.695-.564c-.113-.092-.17-.138-.191-.193a.22.22 0 0 1 0-.152c.02-.055.078-.1.19-.193l.696-.564a1 1 0 0 0 .175-.162.4.4 0 0 0 .065-.138 1 1 0 0 0 .016-.238V6.246c0-.484 0-.727-.095-.912a.87.87 0 0 0-.378-.379c-.186-.094-.428-.094-.913-.094Z",
          "box": 24,
          "bg": "#145FE4"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/onepassword@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/onepassword",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "onepassword",
        "title": "1Password",
        "description": "Your 1Password items from the keyboard, through the op command line tool. Enter copies the password; the username, the one-time code and the item in the app are one key away.",
        "keywords": [
          "1p",
          "op"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M12 0c6.627 0 12 5.373 12 12 0 6.628-5.373 12-12 12S0 18.628 0 12C0 5.373 5.373 0 12 0m-.893 4.86c-.485 0-.727.001-.913.095a.87.87 0 0 0-.378.379c-.094.185-.095.428-.095.912v2.747c0 .12 0 .182.016.238q.02.075.065.138a1 1 0 0 0 .175.162l.695.564c.113.092.17.139.19.194a.22.22 0 0 1 0 .15c-.02.056-.077.102-.19.194l-.695.564a1 1 0 0 0-.175.162.4.4 0 0 0-.065.138 1 1 0 0 0-.016.238v6.019c0 .485 0 .728.095.913a.87.87 0 0 0 .378.378c.186.094.428.094.913.094h1.786c.485 0 .727 0 .913-.094a.87.87 0 0 0 .378-.378c.095-.185.095-.428.095-.913v-2.747c0-.12 0-.182-.016-.238a.4.4 0 0 0-.065-.138 1 1 0 0 0-.175-.162l-.695-.564c-.113-.092-.17-.138-.191-.193a.22.22 0 0 1 0-.152c.02-.055.078-.1.19-.193l.696-.564a1 1 0 0 0 .175-.162.4.4 0 0 0 .065-.138 1 1 0 0 0 .016-.238V6.246c0-.484 0-.727-.095-.912a.87.87 0 0 0-.378-.379c-.186-.094-.428-.094-.913-.094Z",
            "box": 24,
            "bg": "#145FE4"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "account",
            "label": "Account",
            "description": "Passed as --account to every op call: a shorthand, sign-in address, account id or user id. Empty uses the CLI's default.",
            "placeholder": "my.1password.com",
            "default": ""
          },
          {
            "kind": "list",
            "id": "vaults",
            "label": "Vaults",
            "description": "Only these vaults are listed, and each becomes a filter in the palette. Empty lists every vault. A change takes effect when the extension host restarts.",
            "placeholder": "Personal",
            "default": []
          },
          {
            "kind": "number",
            "id": "ttl",
            "label": "Refresh after",
            "description": "Seconds the item list is kept before op is asked again. Refresh in the panel asks at once.",
            "min": 0,
            "max": 86400,
            "unit": "seconds",
            "default": 300
          }
        ],
        "store": {
          "tagline": "Copy a 1Password password, username or one-time code",
          "category": "integration",
          "features": [
            "Every item you can see, favourites first, with the vault, the username and the website",
            "`enter` copies the password, `cmd+u` the username, `cmd+t` the current one-time code",
            "`cmd+o` opens the item in the 1Password app",
            "Search by website, username, category, vault or tag, so `github.com` finds the login",
            "Secrets are fetched only when you copy one and never kept in the list, the index or a log",
            "Signed out, or without the op tool, one row says how to sign in or where to get it"
          ],
          "permissions": [
            "op"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-items.png",
              "caption": "Items with their vault, username and website, favourites first"
            },
            {
              "file": "2-detail.png",
              "caption": "The detail pane (cmd+I): the vault over the title, its category and tags, the username, website and when it changed"
            },
            {
              "file": "3-actions.png",
              "caption": "Copy the password, the username or the one-time code, or open the app"
            },
            {
              "file": "4-vault.png",
              "caption": "The vault dropdown (Tab) narrows the list to one of the vaults in the settings: Work"
            }
          ],
          "actions": [
            {
              "title": "Copy password",
              "description": "`op item get --fields label=password --reveal`; \"Copied password\" in the HUD.",
              "keys": "enter"
            },
            {
              "title": "Copy username",
              "keys": "cmd+u"
            },
            {
              "title": "Copy one-time code",
              "description": "The current TOTP.",
              "keys": "cmd+t"
            },
            {
              "title": "Open in 1Password",
              "description": "The app's own view-item link.",
              "keys": "cmd+o"
            }
          ]
        },
        "palettes": {
          "items": {
            "title": "1Password",
            "kind": "list",
            "lazy": "visit",
            "description": "Every item you can see, favourites first.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the password"
              },
              {
                "keys": "cmd+u",
                "title": "Copy the username"
              },
              {
                "keys": "cmd+t",
                "title": "Copy the one-time code"
              },
              {
                "keys": "cmd+o",
                "title": "Open in 1Password"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/onepassword",
      "tagline": "Copy a 1Password password, username or one-time code",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/onepassword/screenshots/1-items-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/1-items.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/4-vault-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/4-vault.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/onepassword/screenshots/1-items.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/4-vault.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/onepassword/screenshots/1-items-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/onepassword/screenshots/4-vault-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "otp",
      "kind": "registry",
      "title": "Verification Codes",
      "description": "One-time codes from your recent text messages, newest first, with who sent them. Enter pastes the code into the app in front; a bar item shows a new code as it arrives.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰍩",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/otp@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/otp",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "otp",
        "title": "Verification Codes",
        "description": "One-time codes from your recent text messages, newest first, with who sent them. Enter pastes the code into the app in front; a bar item shows a new code as it arrives.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰍩",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "number",
            "id": "hours",
            "label": "Look back",
            "description": "How many hours of messages to scan for codes.",
            "min": 1,
            "max": 720,
            "unit": "hours",
            "default": 24
          },
          {
            "kind": "list",
            "id": "senders",
            "label": "Ignore senders",
            "description": "Senders whose messages are never listed, as Messages shows them (a shortcode like AKBANK, a number, an email). Case does not matter.",
            "placeholder": "AKBANK",
            "default": []
          },
          {
            "kind": "path",
            "id": "db",
            "label": "Messages database",
            "description": "The chat.db to read. ~ is expanded.",
            "pick": "file",
            "default": "~/Library/Messages/chat.db"
          },
          {
            "kind": "path",
            "id": "contacts",
            "label": "Contacts database",
            "description": "An AddressBook-v22.abcddb whose names replace phone numbers; empty means every source under ~/Library/Application Support/AddressBook.",
            "pick": "file",
            "default": ""
          }
        ],
        "palettes": {
          "otp": {
            "title": "Verification Codes",
            "description": "Codes from the last day of messages, Today and Earlier.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Paste the code"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the code"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the sender"
              }
            ]
          }
        },
        "bar": {
          "latest-code": {
            "title": "Latest code",
            "description": "The newest verification code on the strip for a minute after it arrives; the popover shows it large with the sender, the minute counting down and the two codes before it; Enter copies it.",
            "refresh": {
              "every": 10
            },
            "mocks": {
              "fresh": {
                "title": "A code just arrived",
                "item": {
                  "icon": "",
                  "title": "482913",
                  "color": "green",
                  "tooltip": "Akbank: Akbank Mobil giris kodunuz: 482913. Kodu kimseyle paylasmayin."
                }
              },
              "late": {
                "title": "Forty seconds in, the minute nearly up",
                "item": {
                  "icon": "",
                  "title": "731064",
                  "color": "green",
                  "tooltip": "Google: G-731064 is your Google verification code."
                }
              },
              "quiet": {
                "title": "No code in the last minute",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "",
                    "tooltip": "No recent code"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the code (concealed, clears after 30 s)"
              },
              {
                "keys": "p",
                "title": "Paste the code into the app in front"
              },
              {
                "keys": "s",
                "title": "Copy the sender"
              },
              {
                "keys": "o",
                "title": "Open the Verification Codes palette"
              }
            ]
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Paste one-time codes from your text messages",
          "category": "integration",
          "features": [
            "Codes from the last 24 hours of Messages on macOS, newest first, the sender named from Contacts",
            "Spots codes in English and Turkish messages, skipping amounts, dates and phone numbers",
            "A code that just arrived is the first row and shows up at the root",
            "A bar item shows the newest code for a minute, with the sender and the codes before it",
            "Copied codes stay out of clipboard history, and the previous clipboard comes back after 30 seconds"
          ],
          "permissions": [
            "full-disk-access",
            "accessibility"
          ],
          "platforms": [
            "macos"
          ],
          "screenshots": [
            {
              "file": "1-codes.png",
              "caption": "Today's codes and yesterday's: the sender, the message, the code as a green tag, how long ago it came"
            },
            {
              "file": "2-detail.png",
              "caption": "The detail pane: the code large, who sent it with the number and when, the whole message"
            },
            {
              "file": "3-actions.png",
              "caption": "Paste the code into the app in front, copy it (concealed, gone in 30 s), or copy the sender"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the code that just arrived, in green, for a minute",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the code large, who sent it, the minute counting down, the two codes before it; Enter copies",
              "kind": "bar",
              "box": [
                400,
                64,
                840,
                728
              ]
            },
            {
              "file": "bar-popover-late.png",
              "caption": "A code forty seconds in: the bar nearly run down, the item gone twenty seconds later",
              "kind": "bar",
              "box": [
                400,
                64,
                840,
                728
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the key glyph and the code, both green",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Paste code",
              "description": "Hides, then pastes into the app that was in front.",
              "keys": "enter"
            },
            {
              "title": "Copy code",
              "keys": "cmd+c"
            },
            {
              "title": "Copy sender",
              "description": "As Messages stores it.",
              "keys": "cmd+shift+c"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/otp",
      "tagline": "Paste one-time codes from your text messages",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/otp/screenshots/1-codes-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/1-codes.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover-late-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover-late.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/otp/screenshots/1-codes.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/3-actions.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover-late.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/otp/screenshots/1-codes-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/3-actions-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover-late-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/otp/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "latest-code",
          "title": "Latest code",
          "description": "The newest verification code on the strip for a minute after it arrives; the popover shows it large with the sender, the minute counting down and the two codes before it; Enter copies it.",
          "refresh": {
            "every": 10
          },
          "refresh_words": "every 10s"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "power",
      "kind": "bundled",
      "title": "Battery \u0026 Power",
      "description": "Battery level and time left, and with the optional power watcher, where the power goes: the draw over the last hours, what uses power now and why, and what used the battery today, this week and ever.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰁹",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/power@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/power",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "power",
        "title": "Battery \u0026 Power",
        "description": "Battery level and time left, and with the optional power watcher, where the power goes: the draw over the last hours, what uses power now and why, and what used the battery today, this week and ever.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰁹",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "power_state_file",
            "label": "Power watcher state",
            "description": "Optional state.json written by the `power` watcher. It adds measured draw, warnings and top consumers; a stale file is ignored.",
            "pick": "file",
            "default": "~/.local/share/power/state.json"
          }
        ],
        "store": {
          "tagline": "Battery level, and exactly what is draining it",
          "category": "system",
          "features": [
            "The level, the power source and the time left in one sentence (`Drawing 12 W · 1 h 48 min left`)",
            "With the `power` watcher: six hours of draw as a chart, with charging stretches and the charge level over it",
            "What uses power now: the split between apps, chip and screen, and each process with its watts and why",
            "What used the battery today, over 7 days and all time, in watt-hours and as a share",
            "Battery health, cycle count and temperature at a glance",
            "A bar item that stays hidden while all is well and shows up for a low battery or a heavy draw"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-now.png",
              "caption": "Now: the level and six hours of draw on the left; the warning, where the watts go and what uses them on the right"
            },
            {
              "file": "2-today.png",
              "caption": "Today: what used the battery in watt-hours with each one's share, the screen and the rest explained"
            },
            {
              "file": "3-week.png",
              "caption": "7 days: where the week's watt-hours went, the costliest process under the cursor a key away from Processes"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the level, the draw and the warning that made it surface",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "Hover opens the popover: the level, the last hour's draw, the warning and what uses power now",
              "kind": "bar",
              "box": [
                254,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the level, draw and warning as one strip",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Find in Processes",
              "description": "The process under the cursor, typed into the Processes palette (to quit it from there).",
              "keys": "enter"
            },
            {
              "title": "Next / previous tab",
              "description": "Now, Today, 7 days, All time; also 1 to 4.",
              "keys": "tab"
            },
            {
              "title": "Copy name",
              "keys": "cmd+c"
            },
            {
              "title": "Open Battery settings",
              "keys": "s"
            },
            {
              "title": "Refresh",
              "description": "Re-reads the watcher and its windows now.",
              "keys": "cmd+r"
            }
          ]
        },
        "palettes": {
          "power": {
            "title": "Battery \u0026 Power",
            "kind": "view",
            "description": "The level, six hours of draw and the battery's health on the left; on the right, tabs for what uses power now and what used the battery today, this week and ever.",
            "keys": [
              {
                "keys": "enter",
                "title": "Find the process in Processes (on a bookkeeping line: Battery settings)"
              },
              {
                "keys": "tab",
                "title": "Next tab (shift+tab, left, right, h, l; 1 to 4 pick one)"
              },
              {
                "keys": "down",
                "title": "Next row (up, j, k)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the name"
              },
              {
                "keys": "s",
                "title": "Open Battery settings"
              },
              {
                "keys": "cmd+r",
                "title": "Refresh"
              }
            ]
          }
        },
        "states": {
          "level": {
            "description": "Charge, percent",
            "kind": "number"
          },
          "charging": {
            "description": "On external power",
            "kind": "boolean"
          },
          "draw": {
            "description": "Measured draw in watts from the power watcher; 0 without it",
            "kind": "number"
          },
          "alert": {
            "description": "The power watcher's worst warning: crit, warn, or nothing",
            "kind": "string"
          }
        },
        "bar": {
          "battery": {
            "title": "Battery",
            "description": "Battery level, and the time left once that is the question being asked. Hidden while healthy by its rules: on battery from 50%, on the charger from 20%, unless the power watcher warns or measures a draw of 15 W. Amber at 20%, red at 10% or on a critical warning. Hover shows the popover (the level, the last hour's draw, the warning, what uses power now, today's watt-hours); a click opens the Battery \u0026 Power palette.",
            "refresh": {
              "every": 30,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "healthy": {
                "title": "Healthy, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰂄",
                    "title": "100%",
                    "tooltip": "Full, running on the charger"
                  }
                }
              },
              "draining": {
                "title": "Getting low, the time left beside it",
                "item": {
                  "icon": "󰁻",
                  "title": "24% · 2:57",
                  "tooltip": "Drawing 7.2 W · 2 h 57 min left"
                }
              },
              "shown": {
                "title": "Below the show threshold, nothing wrong",
                "item": {
                  "icon": "󰁿",
                  "title": "42%",
                  "tooltip": "Drawing 6.1 W · 3 h 40 min left"
                }
              },
              "charging": {
                "title": "Charging",
                "item": {
                  "icon": "󰂄",
                  "title": "14%",
                  "tooltip": "Charging · full in 48 min"
                }
              },
              "warning": {
                "title": "Power warning",
                "item": {
                  "icon": "󰁿",
                  "title": "42% · 18.9W · background-burn",
                  "color": "amber",
                  "tooltip": "Drawing 19 W · 1 h 12 min left\ncopilot is using power in the background"
                }
              },
              "critical": {
                "title": "Critical battery",
                "item": {
                  "icon": "󰁺",
                  "title": "8% · 0:22",
                  "color": "red",
                  "tooltip": "On battery · 22 min left"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open Battery \u0026 Power"
              },
              {
                "keys": "s",
                "title": "Open Battery settings"
              }
            ],
            "rules": [
              {
                "id": "fine",
                "when": "not power.charging and power.level \u003e= 50 and not power.alert and power.draw \u003c 15",
                "description": "On battery with plenty left and nothing wrong: nothing to say.",
                "hidden": true
              },
              {
                "id": "plugged",
                "when": "power.charging and power.level \u003e 20 and not power.alert",
                "description": "On the charger past the low mark: nothing to say.",
                "hidden": true
              },
              {
                "id": "low",
                "when": "not power.charging and power.level \u003c= 20",
                "description": "Getting low on battery.",
                "color": "amber"
              },
              {
                "id": "warn",
                "when": "power.alert == 'warn'",
                "description": "The power watcher has a warning (a background burn, a high draw).",
                "color": "amber"
              },
              {
                "id": "critical",
                "when": "not power.charging and power.level \u003c= 10",
                "description": "Nearly out.",
                "color": "red"
              },
              {
                "id": "crit",
                "when": "power.alert == 'crit'",
                "description": "The power watcher's critical warning.",
                "color": "red"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/power",
      "tagline": "Battery level, and exactly what is draining it",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/power/screenshots/1-now-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/1-now.png",
        "https://pal.cagdas.io/extensions/power/screenshots/2-today-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/2-today.png",
        "https://pal.cagdas.io/extensions/power/screenshots/3-week-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/3-week.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/power/screenshots/1-now.png",
        "https://pal.cagdas.io/extensions/power/screenshots/2-today.png",
        "https://pal.cagdas.io/extensions/power/screenshots/3-week.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/power/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/power/screenshots/1-now-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/2-today-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/3-week-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/power/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/power/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "battery",
          "title": "Battery",
          "description": "Battery level, and the time left once that is the question being asked. Hidden while healthy by its rules: on battery from 50%, on the charger from 20%, unless the power watcher warns or measures a draw of 15 W. Amber at 20%, red at 10% or on a critical warning. Hover shows the popover (the level, the last hour's draw, the warning, what uses power now, today's watt-hours); a click opens the Battery \u0026 Power palette.",
          "refresh": {
            "every": 30,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 30s, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "privacy",
      "kind": "registry",
      "title": "Privacy",
      "description": "Which app is using the camera, the microphone or the screen right now, during a call, a screen share or a recording. A bar item appears only while one is in use.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰖠",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/privacy@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/privacy",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "privacy",
        "title": "Privacy",
        "description": "Which app is using the camera, the microphone or the screen right now, during a call, a screen share or a recording. A bar item appears only while one is in use.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰖠",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "See which app has your camera, microphone or screen",
          "category": "system",
          "features": [
            "A bar item that shows up only while the camera, microphone or screen is in use, with a mark for each",
            "Names the app behind it, even when a helper or a command started by the app does the recording",
            "Reads the same record as the macOS menu bar's dots, so a Zoom call or a Meet share is named right",
            "Updates within a second of anything turning on or off",
            "`enter` brings the app forward, `s` opens the privacy settings",
            "Type `camera` or `mic` in the search to see who has it"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Show the app",
              "description": "Brings the app using the sensor forward; a camera with no app opens its privacy settings.",
              "keys": "enter"
            },
            {
              "title": "Open privacy settings",
              "keys": "cmd+,"
            }
          ],
          "screenshots": [
            {
              "file": "1-in-use.png",
              "caption": "One row per app: what it holds and for how long, a screen share and a recording in Terminal included"
            },
            {
              "file": "2-actions.png",
              "caption": "Enter brings the app forward; the privacy settings are a shortcut away"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar only while something is in use, a glyph for each sensor: a call holding the camera and the microphone",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-share.png",
              "caption": "A call sharing its screen: all three glyphs",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: one row per app, what it holds in colour and for how long; Enter brings the app forward",
              "kind": "bar",
              "box": [
                450,
                64,
                840,
                646
              ]
            },
            {
              "file": "bar-popover-share.png",
              "caption": "A call sharing its screen: the screen is named on the app's row too, and a capture by macOS itself reads macOS",
              "kind": "bar",
              "box": [
                438,
                64,
                840,
                646
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the same glyphs on an amber band",
              "kind": "bar"
            }
          ]
        },
        "palettes": {
          "privacy": {
            "title": "Camera, Mic \u0026 Screen",
            "kind": "live",
            "description": "Every app using the camera, the microphone or the screen now, cameras first.",
            "keys": [
              {
                "keys": "enter",
                "title": "Bring the app forward"
              },
              {
                "keys": "cmd+,",
                "title": "Open the sensor's privacy settings"
              }
            ]
          }
        },
        "states": {
          "camera": {
            "description": "A camera is running",
            "kind": "boolean"
          },
          "microphone": {
            "description": "An app is recording from a microphone",
            "kind": "boolean"
          },
          "screen": {
            "description": "An app is sharing or recording the screen, or a Screen Sharing session is attached (macOS)",
            "kind": "boolean"
          }
        },
        "bar": {
          "in-use": {
            "title": "Camera, Mic \u0026 Screen",
            "description": "Off the strip until the camera, the microphone or the screen is in use, then a glyph for each on an amber band, the apps in the tooltip. The popover lists every use; Enter brings the app forward. Re-rendered within a second or two of a change.",
            "keys": [
              {
                "keys": "enter",
                "title": "Bring the focused app forward"
              },
              {
                "keys": "s",
                "title": "Open Privacy \u0026 Security settings"
              },
              {
                "keys": "up, down",
                "title": "Move between the uses; a click on one focuses it"
              }
            ],
            "refresh": {
              "every": 300,
              "on": [
                "privacy",
                "wake"
              ]
            },
            "mocks": {
              "call": {
                "title": "On a call",
                "item": {
                  "icon": "󰖠 󰍬",
                  "background": "amber",
                  "tooltip": "Camera and mic in use\nCamera: MacBook Pro Camera · Microphone: zoom.us"
                }
              },
              "mic": {
                "title": "Recording",
                "item": {
                  "icon": "󰍬",
                  "background": "amber",
                  "tooltip": "Mic in use\nMicrophone: kitty"
                }
              },
              "clear": {
                "title": "Nothing in use",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰖠",
                    "tooltip": "Nothing is using the camera, the microphone or the screen"
                  }
                }
              }
            },
            "rules": [
              {
                "id": "clear",
                "when": "not privacy.camera and not privacy.microphone and not privacy.screen",
                "description": "Nothing in use: off the strip.",
                "hidden": true
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/privacy",
      "tagline": "See which app has your camera, microphone or screen",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/privacy/screenshots/1-in-use-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/1-in-use.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar-share-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar-share.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover-share-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover-share.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/privacy/screenshots/1-in-use.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/2-actions.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar-share.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover-share.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/privacy/screenshots/1-in-use-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/2-actions-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar-share-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover-share-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/privacy/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "in-use",
          "title": "Camera, Mic \u0026 Screen",
          "description": "Off the strip until the camera, the microphone or the screen is in use, then a glyph for each on an amber band, the apps in the tooltip. The popover lists every use; Enter brings the app forward. Re-rendered within a second or two of a change.",
          "refresh": {
            "every": 300,
            "on": [
              "privacy",
              "wake"
            ]
          },
          "refresh_words": "every 5 min, on wake"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "processes",
      "kind": "bundled",
      "title": "Processes",
      "description": "What is running, busiest first, with its memory; type :3000 to see what listens on a port. Kill a process or open it in Activity Monitor.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰍛",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/processes@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/processes",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "processes",
        "title": "Processes",
        "description": "What is running, busiest first, with its memory; type :3000 to see what listens on a port. Kill a process or open it in Activity Monitor.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰍛",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "include_system",
            "label": "System processes",
            "text": "List system processes too (pid below 100, and kernel threads on Linux)",
            "default": false
          }
        ],
        "store": {
          "tagline": "What is running, busiest first, and who holds a port",
          "category": "system",
          "features": [
            "Every process sorted by CPU then memory, with its pid and memory, busy ones tagged with their CPU share",
            "Search by name or pid; `:3000` lists what listens on that port, `:` alone every listener",
            "Filters for your own processes, the top CPU users and the top memory users",
            "Kill or force kill (`cmd+shift+k`) after a confirm, and the list stays open",
            "App icons for processes that belong to an app; `cmd+o` finds the process in Activity Monitor",
            "`cmd+i` shows the process as a page: where it runs from, its CPU, memory and pid large, then parent and user"
          ],
          "permissions": [
            "automation",
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Processes by CPU, then memory: a busy one wears its share as a tag, its pid under the name and its memory on the right"
            },
            {
              "file": "2-port.png",
              "caption": "Type : for every TCP listener: the port as a tag, beside the process that holds it"
            },
            {
              "file": "3-confirm.png",
              "caption": "Enter kills, but asks first: SIGTERM here, Force kill's SIGKILL behind cmd+shift+k"
            },
            {
              "file": "4-actions.png",
              "caption": "Kill, Force kill, Copy PID or open the process in Activity Monitor"
            },
            {
              "file": "5-detail.png",
              "caption": "A process's detail (cmd+I): where it runs from, then its CPU, memory and pid large"
            }
          ],
          "actions": [
            {
              "title": "Kill",
              "description": "SIGTERM, after a confirm.",
              "keys": "enter"
            },
            {
              "title": "Force kill",
              "description": "SIGKILL, after a confirm.",
              "keys": "cmd+shift+k"
            },
            {
              "title": "Copy PID",
              "keys": "cmd+c"
            },
            {
              "title": "Open in Activity Monitor",
              "description": "macOS: brings Activity Monitor up with the pid in its search field.",
              "keys": "cmd+o"
            }
          ]
        },
        "palettes": {
          "processes": {
            "title": "Processes",
            "kind": "input",
            "description": "Every process, by CPU then memory.",
            "keys": [
              {
                "keys": "enter",
                "title": "Kill (asks first)"
              },
              {
                "keys": "cmd+shift+k",
                "title": "Force kill (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the pid"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Activity Monitor (macOS)"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/processes",
      "tagline": "What is running, busiest first, and who holds a port",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/processes/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/2-port-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/2-port.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/3-confirm-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/3-confirm.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/processes/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/2-port.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/3-confirm.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/processes/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/2-port-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/3-confirm-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/processes/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "quicklinks",
      "kind": "bundled",
      "title": "Quicklinks",
      "description": "Your own links, opened with Enter, with a {query} slot for search URLs that you fill in from the search bar. Create and edit them in the panel, start from a library of ready-made searches, and import or export them as JSON.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰌹",
          "bg": "orange"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/quicklinks@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/quicklinks",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "quicklinks",
        "title": "Quicklinks",
        "description": "Your own links, opened with Enter, with a {query} slot for search URLs that you fill in from the search bar. Create and edit them in the panel, start from a library of ready-made searches, and import or export them as JSON.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰌹",
            "bg": "orange"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "import",
            "label": "Import file",
            "pick": "file",
            "description": "A JSON array of {name, url, keywords?} listed alongside your own links, read-only; empty for none.",
            "default": ""
          },
          {
            "kind": "boolean",
            "id": "prefer_existing_tab",
            "label": "Prefer an open tab",
            "text": "Open a link by switching to a browser tab already on that page, when there is one",
            "description": "Asks the browsers (as Browser Tabs does) before opening; a new tab when none has the page.",
            "default": false
          }
        ],
        "store": {
          "tagline": "Your own links, with a slot for search terms",
          "category": "productivity",
          "features": [
            "`enter` opens a link; a url with `{query}` asks for the term right in the search bar",
            "`{selection}`, `{clipboard}` and `{files}` fill in by themselves, so one `enter` translates the selected text",
            "Create a link from the tab in front, pick the browser it opens in, edit with `cmd+e`",
            "A library of 25 ready-made searches (Google, Wikipedia, GitHub, npm, MDN, Maps and more)",
            "Optionally switch to a tab that already has the page open instead of opening another",
            "Import and export as JSON; Raycast's quicklinks export is read as is"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Your links by name: a search link carries its {query} as a tag, one pinned to a browser names it"
            },
            {
              "file": "2-query.png",
              "caption": "A search link asks for its query; Enter opens github.com/search with it filled in"
            },
            {
              "file": "3-actions.png",
              "caption": "Open, Copy URL, Edit, Delete on one of your links"
            },
            {
              "file": "4-form.png",
              "caption": "Create Quicklink: name, url with {query}, keywords, the browser to open with"
            },
            {
              "file": "5-library.png",
              "caption": "The library: 25 ready-made searches, the ones you have tagged added; Enter adds one to your links"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "Opens the url; a {query} link asks for it in the search bar first, one field per placeholder name.",
              "keys": "enter"
            },
            {
              "title": "Add to my quicklinks",
              "description": "In the library: the search saved to your links, once.",
              "keys": "enter"
            },
            {
              "title": "Search with it",
              "description": "In the library: the drill-in with the search, without saving it.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy URL",
              "description": "The url as stored, placeholder included.",
              "keys": "cmd+c"
            },
            {
              "title": "Edit",
              "description": "The form, filled in.",
              "keys": "cmd+e"
            },
            {
              "title": "Delete",
              "description": "Asks first.",
              "keys": "ctrl+x"
            },
            {
              "title": "Create quicklink",
              "description": "The form, on the Create row.",
              "keys": "enter"
            },
            {
              "title": "Import…",
              "description": "A JSON file's links, the ones you already have skipped.",
              "keys": "enter"
            },
            {
              "title": "Export…",
              "description": "Your links to a JSON file.",
              "keys": "enter"
            },
            {
              "title": "Browse library",
              "description": "The library level, on the Browse Library row.",
              "keys": "enter"
            }
          ]
        },
        "links": {
          "open": {
            "description": "Open a quicklink by name",
            "params": {
              "name": {
                "description": "The quicklink's name (or a keyword), case-insensitive",
                "required": true
              },
              "query": {
                "description": "Fills the {query} of a search link; without it the panel opens to ask"
              }
            }
          }
        },
        "palettes": {
          "quicklinks": {
            "title": "Quicklinks",
            "tier": "primary",
            "kind": "list",
            "inline": true,
            "match": "^\\s*([a-z][a-z0-9+.-]*://\\S+|(localhost|[a-z0-9-]+(\\.[a-z0-9-]+)*\\.[a-z]{2,})(:\\d+)?([/?#]\\S*)?)\\s*$",
            "fallback": true,
            "description": "Every quicklink by name and keyword, plus Create Quicklink and Browse Library. At the root a typed web address gets an inline Open row; when nothing matches, every {query} link appears filled with what was typed.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open, with the {query} typed in the bar's field; in the library, add the search"
              },
              {
                "keys": "cmd+enter",
                "title": "In the library, search with it without adding"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the url"
              },
              {
                "keys": "cmd+e",
                "title": "Edit"
              },
              {
                "keys": "ctrl+x",
                "title": "Delete"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/quicklinks",
      "tagline": "Your own links, with a slot for search terms",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/2-query-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/2-query.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/4-form-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/4-form.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/5-library-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/5-library.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/2-query.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/4-form.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/5-library.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/2-query-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/4-form-dark.png",
        "https://pal.cagdas.io/extensions/quicklinks/screenshots/5-library-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "open",
          "url": "pal://quicklinks/open?name=\u003cname\u003e",
          "cli": "pal call quicklinks/open name=\u003cname\u003e",
          "description": "Open a quicklink by name",
          "params": [
            {
              "name": "name",
              "description": "The quicklink's name (or a keyword), case-insensitive",
              "required": true
            },
            {
              "name": "query",
              "description": "Fills the {query} of a search link; without it the panel opens to ask"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "samsungtv",
      "kind": "registry",
      "title": "Samsung TV",
      "description": "A remote for your Samsung TV under the keys, spoken to the TV on your network: the arrows and OK, your apps a digit away, the volume as a slider, the inputs as chips, typing into the TV's own keyboard from yours, turning it on and off, and the menu bar. With IP Remote on in the TV's settings it also knows the input on screen and jumps straight to one, moves the sound between the TV's speakers, Q-Symphony and a soundbar (and reconnects a soundbar gone quiet), sets the exact volume on the soundbar, changes the picture mode and the picture, and opens a web page on the TV. Pairs by pressing Allow on the TV. Its volume, power, inputs and sound output can drive another device's remote too (Settings › Groups).",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M19.8166 10.2808l.0459 2.6934h-.023l-.7793-2.6934h-1.2837v3.3925h.8481l-.0458-2.785h.023l.8366 2.785h1.2264v-3.3925zm-16.149 0l-.6418 3.427h.9284l.4699-3.1175h.0229l.4585 3.1174h.9169l-.6304-3.4269zm5.1805 0l-.424 2.6132h-.023l-.424-2.6132H6.5788l-.0688 3.427h.8596l.023-3.0832h.0114l.573 3.0831h.8711l.5731-3.083h.023l.0228 3.083h.8596l-.0802-3.4269zm-7.2664 2.4527c.0343.0802.0229.1949.0114.2522-.0229.1146-.1031.2292-.3324.2292-.2177 0-.3438-.126-.3438-.3095v-.3323H0v.2636c0 .7679.6074.9971 1.2493.9971.6189 0 1.1346-.2178 1.2149-.7794.0458-.298.0114-.4928 0-.5616-.1605-.722-1.467-.9283-1.5588-1.3295-.0114-.0688-.0114-.1375 0-.1834.023-.1146.1032-.2292.3095-.2292.2063 0 .321.126.321.3095v.2063h.8595v-.2407c0-.745-.6762-.8596-1.1576-.8596-.6074 0-1.1117.2063-1.2034.7564-.023.149-.0344.2866.0114.4585.1376.7106 1.364.9169 1.5358 1.3524m11.152 0c.0343.0803.0228.1834.0114.2522-.023.1146-.1032.2292-.3324.2292-.2178 0-.3438-.126-.3438-.3095v-.3323h-.917v.2636c0 .7564.596.9857 1.2379.9857.6189 0 1.1232-.2063 1.2034-.7794.0459-.298.0115-.4814 0-.5616-.1375-.7106-1.4327-.9284-1.5243-1.318-.0115-.0688-.0115-.1376 0-.1835.0229-.1146.1031-.2292.3094-.2292.1948 0 .321.126.321.3095v.2063h.848v-.2407c0-.745-.6647-.8596-1.146-.8596-.6075 0-1.1004.1948-1.192.7564-.023.149-.023.2866.0114.4585.1376.7106 1.341.9054 1.513 1.3524m2.8882.4585c.2407 0 .3094-.1605.3323-.2522.0115-.0343.0115-.0917.0115-.126v-2.533h.871v2.4642c0 .0688 0 .1948-.0114.2292-.0573.6419-.5616.8482-1.192.8482-.6303 0-1.1346-.2063-1.192-.8482 0-.0344-.0114-.1604-.0114-.2292v-2.4642h.871v2.533c0 .0458 0 .0916.0115.126 0 .0917.0688.2522.3095.2522m7.1518-.0344c.2522 0 .3324-.1605.3553-.2522.0115-.0343.0115-.0917.0115-.126v-.4929h-.3553v-.5043H24v.917c0 .0687 0 .1145-.0115.2292-.0573.6303-.596.8481-1.2034.8481-.6075 0-1.1461-.2178-1.2034-.8481-.0115-.1147-.0115-.1605-.0115-.2293v-1.444c0-.0574.0115-.172.0115-.2293.0802-.6419.596-.8482 1.2034-.8482s1.1347.2063 1.2034.8482c.0115.1031.0115.2292.0115.2292v.1146h-.8596v-.1948s0-.0803-.0115-.1261c-.0114-.0802-.0802-.2521-.3438-.2521-.2521 0-.321.1604-.3438.2521-.0115.0458-.0115.1032-.0115.1605v1.5702c0 .0458 0 .0916.0115.126 0 .0917.0917.2522.3323.2522",
          "box": 24,
          "bg": "#1428A0"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/samsungtv@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/samsungtv",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "samsungtv",
        "title": "Samsung TV",
        "description": "A remote for your Samsung TV under the keys, spoken to the TV on your network: the arrows and OK, your apps a digit away, the volume as a slider, the inputs as chips, typing into the TV's own keyboard from yours, turning it on and off, and the menu bar. With IP Remote on in the TV's settings it also knows the input on screen and jumps straight to one, moves the sound between the TV's speakers, Q-Symphony and a soundbar (and reconnects a soundbar gone quiet), sets the exact volume on the soundbar, changes the picture mode and the picture, and opens a web page on the TV. Pairs by pressing Allow on the TV. Its volume, power, inputs and sound output can drive another device's remote too (Settings › Groups).",
        "keywords": [
          "samsung",
          "tv",
          "tizen",
          "remote",
          "smart tv"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M19.8166 10.2808l.0459 2.6934h-.023l-.7793-2.6934h-1.2837v3.3925h.8481l-.0458-2.785h.023l.8366 2.785h1.2264v-3.3925zm-16.149 0l-.6418 3.427h.9284l.4699-3.1175h.0229l.4585 3.1174h.9169l-.6304-3.4269zm5.1805 0l-.424 2.6132h-.023l-.424-2.6132H6.5788l-.0688 3.427h.8596l.023-3.0832h.0114l.573 3.0831h.8711l.5731-3.083h.023l.0228 3.083h.8596l-.0802-3.4269zm-7.2664 2.4527c.0343.0802.0229.1949.0114.2522-.0229.1146-.1031.2292-.3324.2292-.2177 0-.3438-.126-.3438-.3095v-.3323H0v.2636c0 .7679.6074.9971 1.2493.9971.6189 0 1.1346-.2178 1.2149-.7794.0458-.298.0114-.4928 0-.5616-.1605-.722-1.467-.9283-1.5588-1.3295-.0114-.0688-.0114-.1375 0-.1834.023-.1146.1032-.2292.3095-.2292.2063 0 .321.126.321.3095v.2063h.8595v-.2407c0-.745-.6762-.8596-1.1576-.8596-.6074 0-1.1117.2063-1.2034.7564-.023.149-.0344.2866.0114.4585.1376.7106 1.364.9169 1.5358 1.3524m11.152 0c.0343.0803.0228.1834.0114.2522-.023.1146-.1032.2292-.3324.2292-.2178 0-.3438-.126-.3438-.3095v-.3323h-.917v.2636c0 .7564.596.9857 1.2379.9857.6189 0 1.1232-.2063 1.2034-.7794.0459-.298.0115-.4814 0-.5616-.1375-.7106-1.4327-.9284-1.5243-1.318-.0115-.0688-.0115-.1376 0-.1835.0229-.1146.1031-.2292.3094-.2292.1948 0 .321.126.321.3095v.2063h.848v-.2407c0-.745-.6647-.8596-1.146-.8596-.6075 0-1.1004.1948-1.192.7564-.023.149-.023.2866.0114.4585.1376.7106 1.341.9054 1.513 1.3524m2.8882.4585c.2407 0 .3094-.1605.3323-.2522.0115-.0343.0115-.0917.0115-.126v-2.533h.871v2.4642c0 .0688 0 .1948-.0114.2292-.0573.6419-.5616.8482-1.192.8482-.6303 0-1.1346-.2063-1.192-.8482 0-.0344-.0114-.1604-.0114-.2292v-2.4642h.871v2.533c0 .0458 0 .0916.0115.126 0 .0917.0688.2522.3095.2522m7.1518-.0344c.2522 0 .3324-.1605.3553-.2522.0115-.0343.0115-.0917.0115-.126v-.4929h-.3553v-.5043H24v.917c0 .0687 0 .1145-.0115.2292-.0573.6303-.596.8481-1.2034.8481-.6075 0-1.1461-.2178-1.2034-.8481-.0115-.1147-.0115-.1605-.0115-.2293v-1.444c0-.0574.0115-.172.0115-.2293.0802-.6419.596-.8482 1.2034-.8482s1.1347.2063 1.2034.8482c.0115.1031.0115.2292.0115.2292v.1146h-.8596v-.1948s0-.0803-.0115-.1261c-.0114-.0802-.0802-.2521-.3438-.2521-.2521 0-.321.1604-.3438.2521-.0115.0458-.0115.1032-.0115.1605v1.5702c0 .0458 0 .0916.0115.126 0 .0917.0917.2522.3323.2522",
            "box": 24,
            "bg": "#1428A0"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "suggests": [
          "appletv"
        ],
        "controls": [
          "volume",
          "power",
          "inputs",
          "outputs",
          "player"
        ],
        "settings": [
          {
            "kind": "text",
            "id": "device",
            "label": "TV",
            "placeholder": "Living Room",
            "description": "Which paired TV the remote, the root commands and the bar item control, by its name. Empty: the one paired last. d on the remote switches, and writes it here.",
            "default": ""
          },
          {
            "kind": "list",
            "id": "favorites",
            "label": "Dock",
            "placeholder": "An app's name (YouTube) or id",
            "description": "The apps on the remote's dock, in order; each gets a digit, 1 to 8. Empty: the apps you open most. cmd+D in Samsung TV Apps adds or removes one.",
            "default": []
          },
          {
            "kind": "list",
            "id": "inputs",
            "label": "Input names",
            "placeholder": "HDMI 1 = Apple TV",
            "description": "A name for an input, one a line: the chips and the card say it instead of HDMI 1. Naming this input in the remote's cmd+K writes it here.",
            "default": []
          },
          {
            "kind": "boolean",
            "id": "wake",
            "label": "Turn on",
            "text": "Turn the TV on when the remote opens",
            "description": "From standby, and from off with Power On with Mobile on in the TV's settings.",
            "default": false
          },
          {
            "kind": "boolean",
            "id": "stay",
            "label": "Stay connected",
            "text": "Keep the connection open in the background",
            "description": "So the menu bar item follows what is on and a key answers at once. Off, pal connects while the remote is open and lets go a minute and a half after.",
            "default": true
          }
        ],
        "palettes": {
          "remote": {
            "title": "Samsung TV Remote",
            "description": "The arrows move, Enter is OK, Backspace goes back, h is Home; the app or input on screen with the sound output and the picture mode, your dock of apps on the digits, the volume as a slider, the inputs and the sound outputs as chips, the picture on v, a web page on w, and a field that types into the TV whenever it shows its keyboard.",
            "kind": "view",
            "keywords": [
              "control",
              "dpad"
            ],
            "refresh": 15,
            "on": [
              "wake",
              "network",
              "show"
            ],
            "keys": [
              {
                "keys": "up, down, left, right",
                "title": "Move"
              },
              {
                "keys": "enter",
                "title": "OK"
              },
              {
                "keys": "backspace",
                "title": "Back"
              },
              {
                "keys": "h",
                "title": "Home"
              },
              {
                "keys": "space",
                "title": "Play or pause"
              },
              {
                "keys": ", .",
                "title": "Rewind or fast forward"
              },
              {
                "keys": "cmd+left, cmd+right",
                "title": "Previous or next"
              },
              {
                "keys": "- =",
                "title": "Volume down or up"
              },
              {
                "keys": "m",
                "title": "Mute"
              },
              {
                "keys": "p",
                "title": "Turn on or off"
              },
              {
                "keys": "i",
                "title": "Next HDMI input"
              },
              {
                "keys": "b",
                "title": "Next sound output (pairs sound and picture the first time)"
              },
              {
                "keys": "shift+s",
                "title": "Reconnect sound: to the TV's speakers and back"
              },
              {
                "keys": "v",
                "title": "Picture: the mode, the values, the colour tone"
              },
              {
                "keys": "w",
                "title": "Open a web page on the TV"
              },
              {
                "keys": "[ ]",
                "title": "Channel down or up"
              },
              {
                "keys": "1-8",
                "title": "Open a dock app"
              },
              {
                "keys": "a",
                "title": "All apps"
              },
              {
                "keys": "t",
                "title": "Type into the TV (while it shows its keyboard)"
              },
              {
                "keys": "s",
                "title": "The TV's settings"
              },
              {
                "keys": "g",
                "title": "Guide"
              },
              {
                "keys": "e",
                "title": "Exit"
              },
              {
                "keys": "d",
                "title": "Switch TV (with several paired)"
              },
              {
                "keys": "r",
                "title": "Reconnect"
              }
            ]
          },
          "picture": {
            "title": "Samsung TV Picture",
            "description": "The Samsung TV's picture: the mode as chips (Standard, Movie, Filmmaker, Dynamic, Eco), backlight, contrast, brightness, sharpness, colour and tint as sliders, and the colour tone. Needs sound and picture paired.",
            "kind": "view",
            "keywords": [
              "picture mode",
              "filmmaker",
              "backlight",
              "brightness"
            ],
            "keys": [
              {
                "keys": "up, down",
                "title": "Pick a row"
              },
              {
                "keys": "left, right",
                "title": "Change it"
              },
              {
                "keys": "1-5",
                "title": "Picture mode"
              },
              {
                "keys": "r",
                "title": "Read the picture again"
              }
            ]
          },
          "apps": {
            "title": "Samsung TV Apps",
            "description": "The apps on the Samsung TV; Enter opens one on the TV, the one on screen tagged.",
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open on the TV"
              },
              {
                "keys": "cmd+enter",
                "title": "Open, then show the remote"
              },
              {
                "keys": "cmd+d",
                "title": "Add to or remove from the dock"
              },
              {
                "keys": "cmd+w",
                "title": "Close on the TV"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the app id"
              }
            ]
          },
          "commands": {
            "title": "Samsung TV",
            "description": "Turn on and off, home, play or pause, mute and the volume, the inputs, the TV's settings and its guide, as root results; with sound and picture paired also each sound output, Reconnect Sound, the picture modes, and the copied link opened on the TV.",
            "kind": "list",
            "tier": "primary",
            "keys": [
              {
                "keys": "enter",
                "title": "Run"
              }
            ]
          },
          "setup": {
            "title": "Set Up Samsung TV",
            "description": "Finds the Samsung TVs on the network and pairs one: the TV asks whether to allow pal, you press Allow, then once more for sound and picture; ends with a check of what works.",
            "kind": "view",
            "keywords": [
              "pair"
            ],
            "keys": [
              {
                "keys": "1-9",
                "title": "Pair with that TV"
              },
              {
                "keys": "i",
                "title": "Type an address"
              },
              {
                "keys": "r",
                "title": "Look again"
              },
              {
                "keys": "x",
                "title": "Forget a TV"
              }
            ]
          }
        },
        "bar": {
          "tv": {
            "title": "Samsung TV",
            "description": "The app on the Samsung TV's screen, hidden while the TV shows another device's input and in standby. The popover is the remote: the arrows, the buttons, the volume, the inputs, the sound output and the dock on the digits.",
            "refresh": {
              "every": 60,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "keys": [
              {
                "keys": "up, down, left, right",
                "title": "Move"
              },
              {
                "keys": "enter",
                "title": "OK"
              },
              {
                "keys": "backspace",
                "title": "Back"
              },
              {
                "keys": "h",
                "title": "Home"
              },
              {
                "keys": "space",
                "title": "Play or pause"
              },
              {
                "keys": "- =",
                "title": "Volume"
              },
              {
                "keys": "m",
                "title": "Mute"
              },
              {
                "keys": "i",
                "title": "Next HDMI input"
              },
              {
                "keys": "b",
                "title": "Next sound output"
              },
              {
                "keys": "shift+s",
                "title": "Reconnect sound"
              },
              {
                "keys": "1-6",
                "title": "Open a dock app"
              },
              {
                "keys": "t",
                "title": "Type into the TV (while it shows its keyboard)"
              },
              {
                "keys": "p",
                "title": "Turn on or off"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "when",
                "label": "Show",
                "description": "Only while an app runs on the TV itself (on another device's input, like an Apple TV, that device's own item says what plays), or whenever the TV is on.",
                "options": [
                  {
                    "id": "app",
                    "title": "While an app is on screen"
                  },
                  {
                    "id": "on",
                    "title": "While the TV is on"
                  }
                ],
                "default": "app"
              }
            ],
            "mocks": {
              "app": {
                "title": "An app on screen",
                "item": {
                  "icon": "󰔂",
                  "title": "Northlight",
                  "tooltip": "Northlight on Living Room"
                }
              },
              "on": {
                "title": "On, no app in front",
                "item": {
                  "icon": "󰔂",
                  "title": "Living Room",
                  "tooltip": "Living Room is on"
                }
              },
              "standby": {
                "title": "In standby",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰔂",
                    "tooltip": "Living Room is in standby"
                  }
                }
              }
            }
          }
        },
        "states": {
          "power": {
            "description": "The Samsung TV's power: on, standby, off, unknown",
            "kind": "string"
          },
          "app": {
            "description": "The app on the Samsung TV's screen",
            "kind": "string"
          },
          "input": {
            "description": "The input on the Samsung TV's screen, by its name (HDMI 1, or the name given to it); needs sound and picture paired",
            "kind": "string"
          },
          "sound": {
            "description": "Where the Samsung TV's sound plays: TV Speaker, Q-Symphony, Soundbar; needs sound and picture paired",
            "kind": "string"
          },
          "picture": {
            "description": "The Samsung TV's picture mode: Standard, Movie, Filmmaker, Dynamic, Eco; needs sound and picture paired",
            "kind": "string"
          }
        },
        "links": {
          "key": {
            "description": "Press a remote button",
            "params": {
              "name": {
                "description": "up, down, left, right, select, back, home, menu, exit, play_pause, rewind, forward, volume_up, volume_down, mute, power, channel_up, channel_down, guide, info, or a raw KEY_ code",
                "required": true
              },
              "press": {
                "description": "tap (default) or hold"
              }
            }
          },
          "launch": {
            "description": "Open an app on the TV",
            "params": {
              "app": {
                "description": "Its name (YouTube) or id",
                "required": true
              }
            }
          },
          "power": {
            "description": "Turn the TV on or off",
            "params": {
              "to": {
                "description": "on, off or toggle (default)"
              }
            }
          },
          "volume": {
            "description": "The TV's volume",
            "params": {
              "level": {
                "description": "up, down, mute, unmute, or 0 to 100",
                "required": true
              }
            }
          },
          "input": {
            "description": "Switch the input",
            "params": {
              "to": {
                "description": "hdmi (the next HDMI input, the default), source (the input menu), tv, or hdmi1 to hdmi4 (with sound and picture paired)"
              }
            }
          },
          "type": {
            "description": "Type into the text field the TV shows (its own keyboard, open), then submit it",
            "params": {
              "text": {
                "description": "The text",
                "required": true
              }
            }
          },
          "sound": {
            "description": "Move the sound, or reconnect it (to the TV's speakers and back, for a soundbar gone quiet); needs sound and picture paired",
            "params": {
              "to": {
                "description": "reconnect, tv (its speakers), or an output by name (q-symphony, soundbar)",
                "required": true
              }
            }
          },
          "picture": {
            "description": "Set the picture mode; needs sound and picture paired",
            "params": {
              "mode": {
                "description": "standard, movie, filmmaker, dynamic or eco",
                "required": true
              }
            }
          },
          "open": {
            "description": "Open a web page in the TV's browser; needs sound and picture paired",
            "params": {
              "url": {
                "description": "The page",
                "required": true
              }
            }
          }
        },
        "store": {
          "tagline": "Your Samsung TV's remote, apps, volume, inputs, sound and picture, from the keyboard",
          "category": "media",
          "features": [
            "The arrows and OK, Back and Home under the keys; each part of the pad lights as you press",
            "Your dock of apps on the digits, the one on screen marked; every app at the root: type `youtube`, press Enter",
            "The volume as a slider and m to mute, set on the TV itself and, with IP Remote on, exactly on the soundbar too",
            "The inputs as chips, the one on screen lit, a click jumps there; name them (HDMI 1 = Apple TV) and the card says so",
            "The sound output as chips: the TV's speakers, Q-Symphony or a soundbar; shift+S reconnects a soundbar gone quiet, from the root or a link as well",
            "The picture on v: the mode (Filmmaker, Movie, Standard…), backlight, contrast and the rest as sliders, the colour tone",
            "w opens a web page on the TV, the link you copied already in the field",
            "When the TV shows its keyboard, a field opens here: type with your keyboard, Enter sends it",
            "Turns the TV off, and on from standby or off (Wake-on-LAN)",
            "A menu bar item with the app on screen; its popover is the remote",
            "With an Apple TV in the same group, the Apple TV's remote sets this TV's volume, inputs and sound output and turns both on",
            "With Apple TV installed too, o opens the Apple TV's remote over this one and Escape comes back",
            "Guided setup: finds the TV, you press Allow on it (once more for sound and picture), and it checks what works"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-remote.png",
              "caption": "The remote: the arrows and OK, what is on with its input, sound output and picture mode, your apps on the digits, the inputs, the sound output and the volume"
            },
            {
              "file": "2-typing.png",
              "caption": "The TV shows its keyboard and a field opens here: type with yours, Enter sends it"
            },
            {
              "file": "3-apps.png",
              "caption": "Every app on the TV; Enter opens it, cmd+D puts it on the dock"
            },
            {
              "file": "4-commands.png",
              "caption": "At the root: on or off, each input, each sound output and Reconnect Sound, the picture modes"
            },
            {
              "file": "5-picture.png",
              "caption": "The picture on v: the mode as chips, each value a slider, the colour tone"
            },
            {
              "file": "6-ready.png",
              "caption": "Guided setup: press Allow on the TV, then a check of what works, read from the TV itself"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the app on the TV's screen",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the remote: the arrows, the buttons, the volume, the inputs, the sound output and the dock",
              "kind": "bar",
              "box": [
                386,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the TV mark and the app",
              "kind": "bar"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/samsungtv",
      "tagline": "Your Samsung TV's remote, apps, volume, inputs, sound and picture, from the keyboard",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/1-remote-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/1-remote.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/2-typing-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/2-typing.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/3-apps-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/3-apps.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/4-commands-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/4-commands.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/5-picture-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/5-picture.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/6-ready-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/6-ready.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/1-remote.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/2-typing.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/3-apps.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/4-commands.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/5-picture.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/6-ready.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/1-remote-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/2-typing-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/3-apps-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/4-commands-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/5-picture-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/6-ready-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/samsungtv/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "tv",
          "title": "Samsung TV",
          "description": "The app on the Samsung TV's screen, hidden while the TV shows another device's input and in standby. The popover is the remote: the arrows, the buttons, the volume, the inputs, the sound output and the dock on the digits.",
          "refresh": {
            "every": 60,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "key",
          "url": "pal://samsungtv/key?name=\u003cname\u003e",
          "cli": "pal call samsungtv/key name=\u003cname\u003e",
          "description": "Press a remote button",
          "params": [
            {
              "name": "name",
              "description": "up, down, left, right, select, back, home, menu, exit, play_pause, rewind, forward, volume_up, volume_down, mute, power, channel_up, channel_down, guide, info, or a raw KEY_ code",
              "required": true
            },
            {
              "name": "press",
              "description": "tap (default) or hold"
            }
          ]
        },
        {
          "route": "launch",
          "url": "pal://samsungtv/launch?app=\u003capp\u003e",
          "cli": "pal call samsungtv/launch app=\u003capp\u003e",
          "description": "Open an app on the TV",
          "params": [
            {
              "name": "app",
              "description": "Its name (YouTube) or id",
              "required": true
            }
          ]
        },
        {
          "route": "power",
          "url": "pal://samsungtv/power",
          "cli": "pal call samsungtv/power",
          "description": "Turn the TV on or off",
          "params": [
            {
              "name": "to",
              "description": "on, off or toggle (default)"
            }
          ]
        },
        {
          "route": "volume",
          "url": "pal://samsungtv/volume?level=\u003clevel\u003e",
          "cli": "pal call samsungtv/volume level=\u003clevel\u003e",
          "description": "The TV's volume",
          "params": [
            {
              "name": "level",
              "description": "up, down, mute, unmute, or 0 to 100",
              "required": true
            }
          ]
        },
        {
          "route": "input",
          "url": "pal://samsungtv/input",
          "cli": "pal call samsungtv/input",
          "description": "Switch the input",
          "params": [
            {
              "name": "to",
              "description": "hdmi (the next HDMI input, the default), source (the input menu), tv, or hdmi1 to hdmi4 (with sound and picture paired)"
            }
          ]
        },
        {
          "route": "type",
          "url": "pal://samsungtv/type?text=\u003ctext\u003e",
          "cli": "pal call samsungtv/type text=\u003ctext\u003e",
          "description": "Type into the text field the TV shows (its own keyboard, open), then submit it",
          "params": [
            {
              "name": "text",
              "description": "The text",
              "required": true
            }
          ]
        },
        {
          "route": "sound",
          "url": "pal://samsungtv/sound?to=\u003cto\u003e",
          "cli": "pal call samsungtv/sound to=\u003cto\u003e",
          "description": "Move the sound, or reconnect it (to the TV's speakers and back, for a soundbar gone quiet); needs sound and picture paired",
          "params": [
            {
              "name": "to",
              "description": "reconnect, tv (its speakers), or an output by name (q-symphony, soundbar)",
              "required": true
            }
          ]
        },
        {
          "route": "picture",
          "url": "pal://samsungtv/picture?mode=\u003cmode\u003e",
          "cli": "pal call samsungtv/picture mode=\u003cmode\u003e",
          "description": "Set the picture mode; needs sound and picture paired",
          "params": [
            {
              "name": "mode",
              "description": "standard, movie, filmmaker, dynamic or eco",
              "required": true
            }
          ]
        },
        {
          "route": "open",
          "url": "pal://samsungtv/open?url=\u003curl\u003e",
          "cli": "pal call samsungtv/open url=\u003curl\u003e",
          "description": "Open a web page in the TV's browser; needs sound and picture paired",
          "params": [
            {
              "name": "url",
              "description": "The page",
              "required": true
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "screenshots",
      "kind": "bundled",
      "title": "Screenshots",
      "description": "Capture an area, a window or the whole screen to a file or the clipboard, then find the screenshots you took, newest first with thumbnails. Open, reveal, copy the image, its path or a markdown link, read its text, or trash it.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰄀",
          "bg": "teal"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/screenshots@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/screenshots",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "screenshots",
        "title": "Screenshots",
        "description": "Capture an area, a window or the whole screen to a file or the clipboard, then find the screenshots you took, newest first with thumbnails. Open, reveal, copy the image, its path or a markdown link, read its text, or trash it.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰄀",
            "bg": "teal"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "destination",
            "label": "Capture to",
            "description": "Where a capture goes on Enter; cmd+c on a Capture row takes the other one for that shot.",
            "options": [
              {
                "id": "file",
                "title": "A file in the screenshots folder"
              },
              {
                "id": "clipboard",
                "title": "The clipboard"
              }
            ],
            "default": "file"
          },
          {
            "kind": "path",
            "id": "folder",
            "label": "Folder",
            "pick": "folder",
            "description": "Where captures land and the recent list reads. Empty: what macOS uses (`defaults read com.apple.screencapture location`, else the Desktop); on Linux ~/Pictures/Screenshots when it exists, else ~/Pictures.",
            "placeholder": "~/Desktop",
            "default": ""
          },
          {
            "kind": "number",
            "id": "timer",
            "label": "Timer",
            "description": "Seconds the delayed capture (cmd+enter on a Capture row) waits before the shot.",
            "min": 1,
            "max": 60,
            "unit": "seconds",
            "default": 3
          },
          {
            "kind": "boolean",
            "id": "sound",
            "label": "Shutter sound",
            "text": "Play the capture sound",
            "description": "macOS plays one unless told not to.",
            "default": false
          },
          {
            "kind": "boolean",
            "id": "all_files",
            "label": "Every image",
            "text": "List every image and recording in the folder",
            "description": "Off: only files named like macOS's captures (Screenshot ..., Screen Recording ...).",
            "default": false
          },
          {
            "kind": "number",
            "id": "limit",
            "label": "Rows",
            "description": "At most this many recent screenshots.",
            "min": 1,
            "max": 500,
            "default": 50
          },
          {
            "kind": "boolean",
            "id": "ocr_concealed",
            "label": "OCR copies concealed",
            "text": "Text read from a screenshot never enters the clipboard history",
            "default": false
          }
        ],
        "store": {
          "tagline": "Take a screenshot, then find, copy or read the ones you took",
          "category": "system",
          "features": [
            "Capture an area, a window or the screen, to a file or the clipboard, now or after a timer",
            "Your screenshots and recordings newest first, with a thumbnail, pixel size, file size and age",
            "Copy the image, its path or a markdown image link, or copy the text in it (macOS)",
            "Mark several with `tab` to open, copy or trash them together",
            "A screenshot from the last two minutes is the first thing you see when the panel opens",
            "`cmd+i` shows the picture large with its folder, size and time"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Capture an area, a window or the screen, then the folder's screenshots newest first, with thumbnails, pixel sizes and ages"
            },
            {
              "file": "2-actions.png",
              "caption": "Open or reveal it, copy the image, its path or a markdown tag, read its text, or trash it"
            },
            {
              "file": "3-detail.png",
              "caption": "The detail pane: its folder and name, the pixels and size, the picture itself and when it was taken"
            }
          ],
          "actions": [
            {
              "title": "Capture",
              "description": "On a Capture row: to a file in the folder, or to the clipboard when the setting says so.",
              "keys": "enter"
            },
            {
              "title": "Capture after 3 s",
              "description": "The same shot after the timer.",
              "keys": "cmd+enter"
            },
            {
              "title": "Capture to the clipboard",
              "description": "The other destination for this one shot.",
              "keys": "cmd+c"
            },
            {
              "title": "Open",
              "description": "On a screenshot: the file in its app; marked rows together.",
              "keys": "enter"
            },
            {
              "title": "Reveal in Finder",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy image",
              "description": "The file itself onto the clipboard: a paste in a chat or a document drops the picture.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy path",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy as markdown image",
              "description": "`![Screenshot 2026-09-17 at 14.03.22](/path/Screenshot%202026-09-17%20at%2014.03.22.png)`.",
              "keys": "cmd+m"
            },
            {
              "title": "Copy text (OCR)",
              "description": "The text in the picture onto the clipboard.",
              "keys": "cmd+shift+t"
            },
            {
              "title": "Move to Trash",
              "description": "Asks first; marked rows together.",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "screenshots": {
            "title": "Screenshots",
            "kind": "live",
            "remember": false,
            "tier": "primary",
            "description": "Capture rows first, then the screenshots folder newest first with thumbnails, sizes and ages.",
            "keys": [
              {
                "keys": "enter",
                "title": "Capture, or open the screenshot"
              },
              {
                "keys": "cmd+enter",
                "title": "Capture after the timer, or reveal the file"
              },
              {
                "keys": "cmd+c",
                "title": "Capture to the other destination, or copy the image"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the path"
              },
              {
                "keys": "cmd+m",
                "title": "Copy as a markdown image"
              },
              {
                "keys": "cmd+shift+t",
                "title": "Copy the text in it (OCR)"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash"
              },
              {
                "keys": "tab",
                "title": "Mark the row for a multi pick"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/screenshots",
      "tagline": "Take a screenshot, then find, copy or read the ones you took",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/screenshots/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/3-detail-dark.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/3-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/screenshots/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/3-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/screenshots/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/screenshots/screenshots/3-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "scripts",
      "kind": "bundled",
      "title": "Scripts and data files",
      "description": "Lists from shell scripts and data files, with no extension to write: point it at a script that prints JSON lines, a JSON or TOML file, or a folder of script commands. Raycast script commands work as they are.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰆍",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/scripts@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/scripts",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "scripts",
        "title": "Scripts and data files",
        "description": "Lists from shell scripts and data files, with no extension to write: point it at a script that prints JSON lines, a JSON or TOML file, or a folder of script commands. Raycast script commands work as they are.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰆍",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "config",
            "label": "v1 config",
            "description": "A pal v1 config.toml; every [palette.\u003cname\u003e] in it becomes a palette here.",
            "pick": "file",
            "placeholder": "~/.config/pal/config.toml",
            "default": "~/.config/pal/config.toml"
          },
          {
            "kind": "list",
            "id": "skip",
            "label": "Skip",
            "description": "v1 palette names not to load, because a native extension covers them.",
            "placeholder": "calc",
            "default": [
              "combine",
              "pals",
              "apps",
              "bookmarks",
              "calc",
              "emoji",
              "clipboard"
            ]
          },
          {
            "kind": "path",
            "id": "v1_repo",
            "label": "v1 checkout",
            "description": "The v1 checkout: where github:zcag/pal/... bases resolve when v1's plugin cache (~/.local/share/pal) has no copy, and where a base under a v1 checkout missing on this box is looked up. ~/proj/pal is tried when this path has no plugins.",
            "pick": "folder",
            "default": "~/proj/pal-v1"
          },
          {
            "kind": "path",
            "id": "commands",
            "label": "Script commands",
            "description": "A folder of single-file script commands: every executable in it with a # @pal.title line in its header (or Raycast's # @raycast.title) is one row of the Script Commands palette. Watched: a saved file shows on the next listing.",
            "pick": "folder",
            "placeholder": "~/.config/pal/commands",
            "default": "~/.config/pal/commands"
          },
          {
            "kind": "number",
            "id": "timeout",
            "label": "Script timeout",
            "description": "A list or pick script still running after this is killed.",
            "min": 1,
            "max": 300,
            "unit": "s",
            "default": 30
          },
          {
            "kind": "number",
            "id": "preview_max",
            "label": "Previews at once",
            "description": "An item's preview command runs when the detail pane rests on it; at most this many run at the same time. 0 turns previews off.",
            "min": 0,
            "max": 32,
            "unit": "runs",
            "default": 4
          },
          {
            "kind": "number",
            "id": "ttl",
            "label": "Listing lifetime",
            "description": "A palette that declares no ttl keeps its last listing across restarts and shows for this long before its script runs again; a palette's own ttl wins, and a live palette is exempt (it relists on every show unless it sets its own). Default an hour: scripts are the slow tier, and the root answers from the kept listing meanwhile. 0 runs every script on every start.",
            "min": 0,
            "max": 604800,
            "unit": "s",
            "default": 3600
          }
        ],
        "store": {
          "tagline": "Lists from shell scripts, data files and script commands",
          "category": "developer",
          "features": [
            "Each `[palette.\u003cname\u003e]` in your config becomes its own list in the panel",
            "A data file (JSON, JSON lines or TOML) becomes rows with titles, subtitles, links and sections",
            "A script answers with JSON lines and can copy, open, show a message or drill into another list",
            "Script commands: one row per executable in a folder with a `# @pal.title` header, arguments typed in the bar",
            "Raycast's `@raycast.*` headers work unchanged",
            "Lists that refresh on every keystroke or every open, and a detail pane from a shell command"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-data-file.png",
              "caption": "A data-file palette: the rows of links.json in sections, the table's icon unless a row brings its own"
            },
            {
              "file": "2-script.png",
              "caption": "A script palette: the rows run.sh printed as JSON lines, with sections and tags"
            },
            {
              "file": "3-root.png",
              "caption": "A script palette's rows are searchable from the root: deploy finds both deploy commands and the deploy script"
            },
            {
              "file": "4-commands.png",
              "caption": "Script Commands: one row per script in the folder, its mode on the right, an inline one's latest output as its subtitle"
            },
            {
              "file": "5-command-list.png",
              "caption": "A list-mode command: the lines its script printed become rows of their own"
            },
            {
              "file": "6-command-form.png",
              "caption": "A command with @pal.args asks for them before it runs: here the deploy's target and a note"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "An `open` action on the row's url.",
              "keys": "enter"
            },
            {
              "title": "Copy link",
              "description": "A `copy` action on a row field.",
              "keys": "cmd+c"
            },
            {
              "title": "Select",
              "description": "The default of a script palette without actions: run.sh pick with the row in the environment.",
              "keys": "enter"
            },
            {
              "title": "Run",
              "description": "A script command, as its mode says: hud shows the first output line, show the whole output, list its rows, silent nothing. Its @pal.args are typed in the bar first ($1, $2, ... in header order). Asks first with @pal.confirm.",
              "keys": "enter"
            },
            {
              "title": "Open script",
              "description": "The command's file in its editor.",
              "keys": "cmd+o"
            },
            {
              "title": "Copy output",
              "description": "Runs the command and copies what it printed; its @pal.args are typed in the bar first.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy path",
              "description": "The command's file path.",
              "keys": "cmd+shift+c"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/scripts",
      "tagline": "Lists from shell scripts, data files and script commands",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/scripts/screenshots/1-data-file-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/1-data-file.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/2-script-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/2-script.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/4-commands-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/4-commands.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/5-command-list-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/5-command-list.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/6-command-form-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/6-command-form.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/scripts/screenshots/1-data-file.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/2-script.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/4-commands.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/5-command-list.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/6-command-form.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/scripts/screenshots/1-data-file-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/2-script-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/4-commands-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/5-command-list-dark.png",
        "https://pal.cagdas.io/extensions/scripts/screenshots/6-command-form-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "services",
      "kind": "registry",
      "title": "Services",
      "description": "Start, stop and restart background services: systemd units on Linux, launchd jobs on macOS. Read their logs, and enable or disable a unit.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰒓",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/services@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/services",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "services",
        "title": "Services",
        "description": "Start, stop and restart background services: systemd units on Linux, launchd jobs on macOS. Read their logs, and enable or disable a unit.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰒓",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "number",
            "id": "ttl",
            "label": "Refresh after",
            "description": "Seconds a listing stays good for: the palette lists again on show only once the rows are older than this. Read when the extension loads.",
            "min": 0,
            "max": 3600,
            "unit": "s",
            "default": 10
          },
          {
            "kind": "boolean",
            "id": "confirm_user",
            "label": "Confirm user units",
            "text": "Ask before stopping or restarting a user unit",
            "default": false,
            "description": "System units always ask first; a user unit acts at once unless this is on."
          },
          {
            "kind": "list",
            "id": "agent_dirs",
            "local": true,
            "label": "Agent folders (macOS)",
            "description": "Where the launchd agent plists are read from; the first is yours, the second every user's.",
            "default": [
              "~/Library/LaunchAgents",
              "/Library/LaunchAgents"
            ]
          }
        ],
        "store": {
          "tagline": "Start, stop and restart systemd units and launchd jobs",
          "category": "system",
          "features": [
            "Linux: every systemd unit, user and system, filtered by User, System, Failed or Running, its state in colour",
            "`enter` starts or stops a unit; system units ask first and use sudo or pkexec as allowed",
            "`cmd+l` shows the unit's recent log, `cmd+e` enables or disables it",
            "macOS: your launch agents and every loaded job, tagged running, loaded, exited or not loaded",
            "`enter` loads or unloads a job after a confirm, `cmd+shift+r` restarts it, `cmd+l` shows its plist"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-units.png",
              "caption": "systemd units under the User filter: whether each is enabled, and whether it is running, idle or failed"
            },
            {
              "file": "2-failed.png",
              "caption": "The Failed filter gathers what broke across both managers, in a User and a System section"
            },
            {
              "file": "3-logs.png",
              "caption": "cmd+l shows a unit's journal in the panel: why last night's backup failed"
            },
            {
              "file": "4-agents.png",
              "caption": "On macOS, launchd agents by folder, with their pid and state"
            },
            {
              "file": "5-detail.png",
              "caption": "A unit's detail (cmd+I): its manager and file, the name, failed and enabled as chips, what it is for"
            }
          ],
          "actions": [
            {
              "title": "Stop",
              "description": "systemctl stop on an active unit; a system unit asks first.",
              "keys": "enter"
            },
            {
              "title": "Start",
              "description": "systemctl start on an inactive unit.",
              "keys": "enter"
            },
            {
              "title": "Logs",
              "description": "journalctl -u \u003cunit\u003e -n 200 in the panel.",
              "keys": "cmd+l"
            },
            {
              "title": "Restart",
              "description": "systemctl restart, or launchctl kickstart -k on macOS.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Enable",
              "description": "systemctl enable on a disabled unit file.",
              "keys": "cmd+e"
            },
            {
              "title": "Disable",
              "description": "systemctl disable; a system unit asks first.",
              "keys": "cmd+e"
            },
            {
              "title": "Copy unit name",
              "description": "name.service.",
              "keys": "cmd+c"
            },
            {
              "title": "Unload",
              "description": "macOS: launchctl bootout; asks first.",
              "keys": "enter"
            },
            {
              "title": "Load",
              "description": "macOS: launchctl bootstrap from the plist.",
              "keys": "enter"
            },
            {
              "title": "Show plist",
              "description": "macOS: the plist as XML in the panel.",
              "keys": "cmd+l"
            },
            {
              "title": "Open plist file",
              "keys": "cmd+o"
            },
            {
              "title": "Copy label",
              "keys": "cmd+c"
            }
          ]
        },
        "palettes": {
          "services": {
            "kind": "live",
            "description": "Every service unit (Linux) or launchd job (macOS), with its state.",
            "keys": [
              {
                "keys": "enter",
                "title": "Stop or start (unload or load on macOS)"
              },
              {
                "keys": "cmd+l",
                "title": "Logs (the plist on macOS)"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Restart"
              },
              {
                "keys": "cmd+e",
                "title": "Enable or disable the unit file (Linux)"
              },
              {
                "keys": "cmd+o",
                "title": "Open the plist file (macOS)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the unit name or label"
              },
              {
                "keys": "tab",
                "title": "Next filter: User, System, Failed, Running"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/services",
      "tagline": "Start, stop and restart systemd units and launchd jobs",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/services/screenshots/1-units-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/1-units.png",
        "https://pal.cagdas.io/extensions/services/screenshots/2-failed-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/2-failed.png",
        "https://pal.cagdas.io/extensions/services/screenshots/3-logs-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/3-logs.png",
        "https://pal.cagdas.io/extensions/services/screenshots/4-agents-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/4-agents.png",
        "https://pal.cagdas.io/extensions/services/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/services/screenshots/1-units.png",
        "https://pal.cagdas.io/extensions/services/screenshots/2-failed.png",
        "https://pal.cagdas.io/extensions/services/screenshots/3-logs.png",
        "https://pal.cagdas.io/extensions/services/screenshots/4-agents.png",
        "https://pal.cagdas.io/extensions/services/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/services/screenshots/1-units-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/2-failed-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/3-logs-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/4-agents-dark.png",
        "https://pal.cagdas.io/extensions/services/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "sessions",
      "kind": "registry",
      "title": "Sessions",
      "description": "Every Claude Code, Codex and Copilot CLI session on this machine and what each is doing: working, your turn, waiting on you, or ended. Enter brings the session's terminal to the front.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰚩",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/sessions@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/sessions",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "sessions",
        "title": "Sessions",
        "description": "Every Claude Code, Codex and Copilot CLI session on this machine and what each is doing: working, your turn, waiting on you, or ended. Enter brings the session's terminal to the front.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰚩",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "keywords": [
          "ai",
          "agent",
          "claude",
          "codex",
          "copilot"
        ],
        "settings": [
          {
            "kind": "list",
            "id": "agents",
            "label": "Agents",
            "description": "Which agents' files are read: claude, codex, copilot.",
            "placeholder": "claude",
            "default": [
              "claude",
              "codex",
              "copilot"
            ]
          },
          {
            "kind": "number",
            "id": "stale_minutes",
            "label": "Ended sessions shown for",
            "description": "A session with no process behind it stays listed as ended this long after its last write, so a crash is seen; older ones are only under the Recent filter.",
            "min": 1,
            "max": 1440,
            "unit": "min",
            "default": 30
          },
          {
            "kind": "number",
            "id": "recent_hours",
            "label": "Recent filter",
            "description": "How far back the Recent filter lists sessions to resume.",
            "min": 1,
            "max": 720,
            "unit": "h",
            "default": 24
          },
          {
            "kind": "select",
            "id": "terminal",
            "label": "Terminal",
            "description": "Where Focus looks for the session's window and what Resume opens. Auto tries a tmux pane, then kitty, iTerm2, Terminal, WezTerm, then raises the app the process runs under by its pid; a named one tries tmux then that alone; tmux only stops after the pane.",
            "options": [
              {
                "id": "auto",
                "title": "Auto"
              },
              {
                "id": "kitty",
                "title": "kitty"
              },
              {
                "id": "iterm",
                "title": "iTerm2"
              },
              {
                "id": "terminal",
                "title": "Terminal"
              },
              {
                "id": "wezterm",
                "title": "WezTerm"
              },
              {
                "id": "tmux",
                "title": "tmux only"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "text",
            "id": "editor",
            "label": "Editor",
            "description": "The command Open in editor and Open transcript run (found on PATH, then in Homebrew's and ~/.local/bin); the OS opener when it is not found.",
            "placeholder": "code",
            "default": "code"
          }
        ],
        "links": {
          "state": {
            "description": "Record a session's state from a hook, for ten minutes, over what the files say",
            "params": {
              "agent": {
                "description": "claude, codex or copilot",
                "required": true
              },
              "session": {
                "description": "The session id the CLI gave the hook",
                "required": true
              },
              "state": {
                "description": "working, waiting (your turn) or blocked (a prompt is up)",
                "required": true
              }
            }
          }
        },
        "palettes": {
          "sessions": {
            "title": "Sessions",
            "description": "Every session by state: waiting on you, your turn, working, ended. The pane shows the last exchange and, for a blocked one, the tool call left hanging.",
            "kind": "live",
            "remember": false,
            "tier": "primary",
            "keys": [
              {
                "keys": "enter",
                "title": "Focus the session's terminal (an ended one: resume it in a new terminal)"
              },
              {
                "keys": "cmd+enter",
                "title": "Send the line typed in the bar to a session in a tmux pane"
              },
              {
                "keys": "cmd+t",
                "title": "The transcript as a view: the last entries as a chat, [ for older, c copies the reply, s sends a line over tmux"
              },
              {
                "keys": "cmd+o",
                "title": "Open the transcript in the editor"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Reveal the transcript"
              },
              {
                "keys": "cmd+e",
                "title": "Open the folder in the editor"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the resume command"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the session id"
              },
              {
                "keys": "cmd+d",
                "title": "Kill the process (asks first; works on marked rows)"
              }
            ]
          }
        },
        "states": {
          "working": {
            "description": "Sessions with a turn in progress",
            "kind": "number"
          },
          "waiting": {
            "description": "Sessions waiting on you (your turn, or blocked on a permission)",
            "kind": "number"
          }
        },
        "bar": {
          "sessions": {
            "title": "Sessions",
            "description": "How many sessions are running, with red !N waiting on you, amber ·N your turn, blue …N working; an alarm while one is waiting on you; hidden with none. The popover lists them by state: Enter focuses the terminal, o opens the transcript, r copies the resume command, x kills.",
            "mocks": {
              "working": {
                "title": "Two sessions working",
                "item": {
                  "icon": "󰙴",
                  "segments": [
                    {
                      "id": "working",
                      "text": "2",
                      "color": "blue"
                    }
                  ],
                  "tooltip": "2 sessions: 2 working"
                }
              },
              "attention": {
                "title": "One waiting on you, one your turn",
                "item": {
                  "icon": "󰙴",
                  "segments": [
                    {
                      "id": "blocked",
                      "text": "1",
                      "color": "red"
                    },
                    {
                      "id": "waiting",
                      "text": "1",
                      "color": "amber"
                    }
                  ],
                  "urgent": true,
                  "tooltip": "2 sessions: 1 waiting on you, 1 your turn"
                }
              },
              "mixed": {
                "title": "Every state at once",
                "item": {
                  "icon": "󰙴",
                  "segments": [
                    {
                      "id": "blocked",
                      "text": "1",
                      "color": "red"
                    },
                    {
                      "id": "waiting",
                      "text": "1",
                      "color": "amber"
                    },
                    {
                      "id": "working",
                      "text": "2",
                      "color": "blue"
                    }
                  ],
                  "urgent": true,
                  "tooltip": "5 sessions: 1 waiting on you, 1 your turn, 2 working, 1 ended"
                }
              },
              "ended": {
                "title": "One just ended, nothing running",
                "item": {
                  "icon": "󰙴",
                  "segments": [],
                  "tooltip": "1 session: 1 ended"
                }
              },
              "hidden": {
                "title": "No sessions",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰙴",
                    "tooltip": "No sessions"
                  }
                }
              }
            },
            "refresh": {
              "every": 10,
              "on": [
                "show",
                "wake"
              ]
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Focus the session's terminal (an ended one: resume it)"
              },
              {
                "keys": "t",
                "title": "The transcript as a view over the list"
              },
              {
                "keys": "o",
                "title": "Open the transcript in the editor"
              },
              {
                "keys": "r",
                "title": "Copy the resume command"
              },
              {
                "keys": "x",
                "title": "Kill the process (asks first)"
              },
              {
                "keys": "s",
                "title": "Open the palette on a tmux session's row, to type a line into it"
              },
              {
                "keys": "p",
                "title": "Open the Sessions palette"
              },
              {
                "keys": "up",
                "title": "Move between sessions (or j and k)"
              }
            ]
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Every Claude Code, Codex and Copilot session, and which one needs you",
          "category": "developer",
          "features": [
            "One row per session, sorted by who needs you: waiting on you, your turn, working, ended",
            "Spots a session stuck on a permission prompt; a hook can report the exact state",
            "The last prompt, the last reply, the pending command, the model, folder, branch and token count",
            "`enter` jumps to the session's terminal (tmux, kitty, iTerm2, Terminal, WezTerm); an ended one resumes",
            "`cmd+t` reads the transcript live in the panel; send a line to a tmux session with `cmd+enter`",
            "A bar item counts sessions by state and raises an alarm while one waits on you"
          ],
          "permissions": [
            "ps",
            "lsof",
            "tmux",
            "kitten",
            "wezterm",
            "osascript"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Every Claude Code, Codex and Copilot session on the machine by state: the one waiting on you first, then your turn, working, ended"
            },
            {
              "file": "2-detail.png",
              "caption": "The pane: your last prompt, the agent's last words and the command it is waiting to run; the folder, tokens and process below"
            },
            {
              "file": "3-transcript.png",
              "caption": "cmd+t reads the transcript inside pal: prompts, replies and every tool call with its outcome, live while it runs"
            },
            {
              "file": "4-actions.png",
              "caption": "⌘K on a session: focus its terminal, send a line to its tmux pane, read or reveal the transcript, copy the resume command"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: how many sessions wait on you, are your turn and are working; the glyph turns red while one waits on you",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: a row per session by state; Enter focuses its terminal, r copies the resume command",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                948
              ]
            },
            {
              "file": "bar-popover-transcript.png",
              "caption": "t shows the transcript over the list, the command waiting on you lit",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                954
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the three counts in red, amber and blue",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Focus the terminal",
              "description": "The window the session runs in, in front; a tmux pane is selected on the way.",
              "keys": "enter"
            },
            {
              "title": "Resume in a terminal",
              "description": "On an ended session: a terminal opens in its folder running the resume command.",
              "keys": "enter"
            },
            {
              "title": "Send the line",
              "description": "On a session in a tmux pane: the bar's text typed into it and sent.",
              "keys": "cmd+enter"
            },
            {
              "title": "Transcript",
              "description": "The conversation as a view inside pal, live while the session runs.",
              "keys": "cmd+t"
            },
            {
              "title": "Open transcript in the editor",
              "description": "The transcript file in the editor named in Settings, else the OS's text editor.",
              "keys": "cmd+o"
            },
            {
              "title": "Open in editor",
              "description": "The session's folder in the editor named in Settings, Finder when it is not on PATH.",
              "keys": "cmd+e"
            },
            {
              "title": "Copy resume command",
              "description": "The CLI's own resume line for this session.",
              "keys": "cmd+c"
            },
            {
              "title": "Kill",
              "description": "SIGTERM to the session's process, after a confirm; the transcript stays.",
              "keys": "cmd+d"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/sessions",
      "tagline": "Every Claude Code, Codex and Copilot session, and which one needs you",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/sessions/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/3-transcript-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/3-transcript.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover-transcript-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover-transcript.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/sessions/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/3-transcript.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/4-actions.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover-transcript.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/sessions/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/3-transcript-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/4-actions-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover-transcript-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/sessions/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "sessions",
          "title": "Sessions",
          "description": "How many sessions are running, with red !N waiting on you, amber ·N your turn, blue …N working; an alarm while one is waiting on you; hidden with none. The popover lists them by state: Enter focuses the terminal, o opens the transcript, r copies the resume command, x kills.",
          "refresh": {
            "every": 10,
            "on": [
              "show",
              "wake"
            ]
          },
          "refresh_words": "every 10s, when the panel shows, on wake"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "state",
          "url": "pal://sessions/state?agent=\u003cagent\u003e\u0026session=\u003csession\u003e\u0026state=\u003cstate\u003e",
          "cli": "pal call sessions/state agent=\u003cagent\u003e session=\u003csession\u003e state=\u003cstate\u003e",
          "description": "Record a session's state from a hook, for ten minutes, over what the files say",
          "params": [
            {
              "name": "agent",
              "description": "claude, codex or copilot",
              "required": true
            },
            {
              "name": "session",
              "description": "The session id the CLI gave the hook",
              "required": true
            },
            {
              "name": "state",
              "description": "working, waiting (your turn) or blocked (a prompt is up)",
              "required": true
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "shell",
      "kind": "bundled",
      "title": "Shell",
      "description": "Run a command in your login shell and read its output in the panel, with the exit code and how long it took. Nothing runs until you press Enter, and destructive-looking commands ask first.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰞷",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/shell@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/shell",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "shell",
        "title": "Shell",
        "description": "Run a command in your login shell and read its output in the panel, with the exit code and how long it took. Nothing runs until you press Enter, and destructive-looking commands ask first.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰞷",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "shell",
            "label": "Shell",
            "description": "The shell and its flags; `$SHELL` is your login shell. `-l` loads the login profile (PATH), `-i` the interactive one (aliases); `-c` takes the command. A `zsh -lc` skips the aliases and the interactive noise.",
            "placeholder": "$SHELL -lic",
            "default": "$SHELL -lic"
          },
          {
            "kind": "path",
            "id": "cwd",
            "label": "Working directory",
            "description": "Where commands run; `~` is expanded.",
            "pick": "folder",
            "placeholder": "~",
            "default": "~"
          },
          {
            "kind": "number",
            "id": "timeout",
            "label": "Timeout",
            "description": "A command still running after this is killed (SIGTERM, then SIGKILL) and the view says so; what it printed until then is kept.",
            "min": 1,
            "max": 600,
            "unit": "seconds",
            "default": 10
          },
          {
            "kind": "list",
            "id": "env",
            "label": "Environment",
            "description": "`KEY=VALUE` lines set for every command, on top of the host's environment.",
            "placeholder": "PAGER=cat",
            "default": []
          },
          {
            "kind": "boolean",
            "id": "confirm",
            "label": "Confirm destructive commands",
            "text": "Ask before running a command that removes, overwrites or escalates (rm, sudo, mv, dd, git reset --hard, ...)",
            "default": true
          },
          {
            "kind": "text",
            "id": "terminal",
            "label": "Terminal",
            "description": "What cmd+Enter opens: `Terminal` (default), `iTerm`, `kitty`, `Alacritty`, `WezTerm`, `Ghostty`, or any app name (`open -na \u003cname\u003e --args -e ...`); on Linux a command name (`kitty`, `foot`, `alacritty`, `wezterm`, `ghostty`, ...), else `$TERMINAL`, else the first of those installed.",
            "placeholder": "Terminal",
            "default": ""
          }
        ],
        "store": {
          "tagline": "Run a command, read its output in the panel, run it again",
          "category": "developer",
          "features": [
            "Nothing runs as you type; `rm`, `sudo`, `git reset --hard` and the like ask first",
            "Runs in your login shell, so your PATH, aliases and functions work",
            "Output in the panel: stdout in monospace, stderr in red, the exit code and duration on top",
            "Long commands show the elapsed time and the result lands when they finish",
            "`enter` copies the output, `cmd+enter` opens the command in your terminal, `cmd+r` runs it again",
            "A history of every command with its exit code; type `$ ls` at the root to run it right there"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-run.png",
              "caption": "A command typed: one Run row, nothing has run yet"
            },
            {
              "file": "2-output.png",
              "caption": "The output view: exit 0 and the duration as badges, stdout in mono on the sunken surface"
            },
            {
              "file": "3-stderr.png",
              "caption": "A failing command: stderr in red, exit 1"
            },
            {
              "file": "4-confirm.png",
              "caption": "rm -rf on the way: the confirm card before anything runs"
            },
            {
              "file": "5-history.png",
              "caption": "Shell History: past commands, green or red by how they ended, a failure with its exit code; Enter runs one again"
            }
          ],
          "actions": [
            {
              "title": "Run",
              "description": "The command in the login shell; the output as a view. Asks first when it looks destructive.",
              "keys": "enter"
            },
            {
              "title": "Run in terminal",
              "description": "Opens a terminal window on the command in the working directory.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy command",
              "keys": "cmd+c"
            },
            {
              "title": "Copy output",
              "description": "In the output view: stdout (stderr when there is no stdout) onto the clipboard.",
              "keys": "enter"
            },
            {
              "title": "Open in terminal",
              "description": "In the output view: the same command in a terminal window.",
              "keys": "cmd+enter"
            },
            {
              "title": "Run again",
              "description": "In the output view: the command once more, the view replaced.",
              "keys": "cmd+r"
            },
            {
              "title": "Copy stderr",
              "description": "In the output view.",
              "keys": "cmd+shift+e"
            },
            {
              "title": "Remove from history",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "shell": {
            "title": "Shell",
            "kind": "input",
            "inline": true,
            "match": "^[$\u003e] \\S",
            "description": "Type a command; the one row runs it on Enter and shows the output as a view. At the root `$ ls` or `\u003e ls` lists the same row inline.",
            "keys": [
              {
                "keys": "enter",
                "title": "Run the command (in the view: copy the output)"
              },
              {
                "keys": "cmd+enter",
                "title": "Run it in a terminal window instead (in the view: open one)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the command"
              },
              {
                "keys": "cmd+r",
                "title": "In the view: run it again"
              },
              {
                "keys": "cmd+shift+e",
                "title": "In the view: copy stderr"
              }
            ]
          },
          "history": {
            "title": "Shell History",
            "kind": "input",
            "description": "Every command run here, newest first, with its exit code and duration; Enter runs it again.",
            "keys": [
              {
                "keys": "enter",
                "title": "Run the command again"
              },
              {
                "keys": "cmd+enter",
                "title": "Run it in a terminal window"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the command"
              },
              {
                "keys": "cmd+d",
                "title": "Remove the entry"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/shell",
      "tagline": "Run a command, read its output in the panel, run it again",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/shell/screenshots/1-run-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/1-run.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/2-output-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/2-output.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/3-stderr-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/3-stderr.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/4-confirm-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/4-confirm.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/5-history-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/5-history.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/shell/screenshots/1-run.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/2-output.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/3-stderr.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/4-confirm.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/5-history.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/shell/screenshots/1-run-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/2-output-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/3-stderr-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/4-confirm-dark.png",
        "https://pal.cagdas.io/extensions/shell/screenshots/5-history-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "shortcuts",
      "kind": "bundled",
      "title": "Shortcuts",
      "description": "Every shortcut from Apple's Shortcuts app, grouped by folder. Run one with Enter, with the clipboard or typed text as its input, and see the result when it ends.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M8 1.5 13.5 5 8 8.5 2.5 5Zm0 6.3 2.9 1.8L8 11.4 5.1 9.6Zm-5.5 3.2L8 7.5l5.5 3.5L8 14.5Zm2.6 0L8 12.7l2.9-1.7L8 9.3Z",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/shortcuts@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/shortcuts",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "shortcuts",
        "title": "Shortcuts",
        "description": "Every shortcut from Apple's Shortcuts app, grouped by folder. Run one with Enter, with the clipboard or typed text as its input, and see the result when it ends.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M8 1.5 13.5 5 8 8.5 2.5 5Zm0 6.3 2.9 1.8L8 11.4 5.1 9.6Zm-5.5 3.2L8 7.5l5.5 3.5L8 14.5Zm2.6 0L8 12.7l2.9-1.7L8 9.3Z",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "Run any Apple Shortcut by name, folders as sections",
          "category": "system",
          "features": [
            "Every shortcut findable by name from the root, grouped by its folder",
            "`enter` runs it and shows Done or its output when it finishes, however long it takes",
            "`cmd+enter` runs it on the clipboard text, `cmd+t` on text you type in the bar",
            "`cmd+o` opens it in Shortcuts for editing",
            "A global hotkey for any shortcut, set by its name in your config",
            "macOS 12 and later"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Every Apple Shortcut on this Mac, grouped by its folder and searchable by name or folder"
            },
            {
              "file": "2-actions.png",
              "caption": "Run it as it is, on the clipboard or on text you type, or open it in Shortcuts to edit"
            },
            {
              "file": "3-root.png",
              "caption": "No need to open the palette: a shortcut's name typed at the root finds it"
            },
            {
              "file": "4-form.png",
              "caption": "Run with input: type what the shortcut receives, here the notes a Standup shortcut files"
            }
          ],
          "actions": [
            {
              "title": "Run",
              "description": "Runs the shortcut; the HUD shows Done or its output's first line.",
              "keys": "enter"
            },
            {
              "title": "Run with clipboard",
              "description": "The newest clipboard text as the shortcut's input.",
              "keys": "cmd+enter"
            },
            {
              "title": "Run with input",
              "description": "The input typed in the bar (the row's argument), then the run; a form when picked without it.",
              "keys": "cmd+t"
            },
            {
              "title": "Open in Shortcuts",
              "description": "The shortcut in the Shortcuts app.",
              "keys": "cmd+o"
            },
            {
              "title": "Copy name",
              "description": "The shortcut's name onto the clipboard.",
              "keys": "cmd+c"
            }
          ]
        },
        "palettes": {
          "shortcuts": {
            "title": "Shortcuts",
            "kind": "list",
            "tier": "primary",
            "ttl": 300,
            "description": "Every shortcut, its folder as the section.",
            "keys": [
              {
                "keys": "enter",
                "title": "Run the shortcut"
              },
              {
                "keys": "cmd+enter",
                "title": "Run it with the clipboard as input"
              },
              {
                "keys": "cmd+t",
                "title": "Run it with the input typed in the bar"
              },
              {
                "keys": "cmd+o",
                "title": "Open it in Shortcuts"
              },
              {
                "keys": "cmd+c",
                "title": "Copy its name"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/shortcuts",
      "tagline": "Run any Apple Shortcut by name, folders as sections",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/4-form-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/4-form.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/4-form.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/shortcuts/screenshots/4-form-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "slack",
      "kind": "registry",
      "title": "Slack",
      "description": "What Slack is holding for you: direct messages, mentions and thread replies with who sent them, your channels, search, and your status and Do Not Disturb. Signs in through the Slack desktop app you already use, or a token.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰒱",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/slack@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/slack",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "slack",
        "title": "Slack",
        "description": "What Slack is holding for you: direct messages, mentions and thread replies with who sent them, your channels, search, and your status and Do Not Disturb. Signs in through the Slack desktop app you already use, or a token.",
        "version": "0.1.0",
        "multi": true,
        "icon": {
          "tile": {
            "glyph": "󰒱",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "auth",
            "label": "Sign in",
            "description": "app reads the desktop app's own session (its token from Local Storage and its cookie from the cookie jar, decrypted with the Safe Storage password in the keychain), so it sees exactly your inbox; token uses a user token from a Slack app of your own.",
            "options": [
              {
                "id": "app",
                "title": "The Slack desktop app's session"
              },
              {
                "id": "token",
                "title": "A user token"
              }
            ],
            "default": "app"
          },
          {
            "kind": "secret",
            "id": "token",
            "required": true,
            "label": "Token",
            "only": {
              "auth": "token"
            },
            "description": "A user token (xoxp-...) with channels:read, groups:read, im:read, mpim:read, channels:history, groups:history, im:history, mpim:history, users:read, chat:write, search:read, users.profile:write, users:write, dnd:write. Only with Sign in set to token.",
            "placeholder": "xoxp-...",
            "default": ""
          },
          {
            "kind": "text",
            "id": "workspace",
            "scope": "instance",
            "label": "Workspace",
            "description": "The workspace to use when the app is signed in to several, by id (T...) or domain (acme for acme.slack.com); empty lists every signed-in one, with status and search on the first.",
            "placeholder": "acme",
            "default": ""
          },
          {
            "kind": "list",
            "id": "statuses",
            "label": "Status presets",
            "description": "One per line as :emoji: text (expiry); the expiry is 30m, 2h, 1d or today, or left out for no expiry.",
            "placeholder": ":coffee: Coffee break (15m)",
            "default": [
              ":spiral_calendar_pad: In a meeting (1h)",
              ":knife_fork_plate: Lunch (1h)",
              ":headphones: Focus time (2h)",
              ":house_with_garden: Working from home (today)",
              ":palm_tree: Out of office"
            ]
          },
          {
            "kind": "boolean",
            "id": "presence",
            "label": "Presence dots",
            "text": "A dot on each direct message row: green while the person is active, grey while away",
            "description": "One users.getPresence per person among the unread direct messages, remembered a minute; off makes no such call, for a workspace where many direct messages are open at once.",
            "default": true
          }
        ],
        "palettes": {
          "unreads": {
            "title": "Unreads",
            "description": "Direct messages, mentions and threads addressed to you, then the channels that are only unread; each row with who said what and how long ago.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the conversation in Slack"
              },
              {
                "keys": "cmd+enter",
                "title": "Reply with the message typed in the bar"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Mark as read"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "channels": {
            "title": "Channels",
            "description": "Every channel, group and direct message you are in, with the topic and the member count; a message typed in the bar is sent with cmd+shift+r.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "tier": "catalog",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Slack"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Send the message typed in the bar"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "search": {
            "title": "Search Slack",
            "description": "Slack's message search as you type, its syntax passed through: from:@name, in:#channel, has:link, before:yesterday.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the message in Slack"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the text"
              }
            ]
          },
          "status": {
            "title": "Status",
            "description": "Your status, presence and Do Not Disturb as the first rows; set a status from the presets or type one (text, emoji, expiry in the search bar), clear it, snooze notifications for 30 minutes, an hour, until tomorrow or for the minutes you type, go away or active.",
            "kind": "live",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Set it; Set a status… and Do Not Disturb for… take their values from the bar's fields"
              }
            ]
          }
        },
        "states": {
          "attention": {
            "description": "Direct messages, mentions and thread replies addressed to you",
            "kind": "number"
          },
          "dm": {
            "description": "Unread direct messages",
            "kind": "number"
          },
          "channels": {
            "description": "Channels merely unread",
            "kind": "number"
          }
        },
        "bar": {
          "unreads": {
            "title": "Unreads",
            "description": "What is addressed to you (direct messages, mentions, thread replies) as a count, hidden at zero, red while a direct message waits; the popover lists them with the sender, the message and the time, the channels that are only unread, and replies, marks read and opens from the keys.",
            "refresh": {
              "every": 120,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "settings": [
              {
                "kind": "number",
                "id": "refresh",
                "label": "Refresh",
                "description": "Seconds between refreshes of the item; it also refreshes when the panel shows, after a wake and when the network is back.",
                "min": 10,
                "max": 3600,
                "unit": "s",
                "default": 120
              }
            ],
            "mocks": {
              "mentions": {
                "title": "Mentions and thread replies",
                "item": {
                  "icon": "󰒱",
                  "badge": 3,
                  "urgent": false,
                  "tooltip": "2 mentions, 1 thread reply; 4 channels unread"
                }
              },
              "dm": {
                "title": "A direct message waits",
                "item": {
                  "icon": "󰒱",
                  "badge": 2,
                  "urgent": true,
                  "tooltip": "1 direct message, 1 mention"
                }
              },
              "one": {
                "title": "One mention",
                "item": {
                  "icon": "󰒱",
                  "badge": 1,
                  "urgent": false,
                  "tooltip": "1 mention"
                }
              },
              "channels": {
                "title": "Only channels unread, kept on the bar (Bar item: unread)",
                "item": {
                  "icon": "󰒱",
                  "color": "muted",
                  "tooltip": "4 channels unread"
                }
              },
              "clear": {
                "title": "Nothing addressed to you",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰒱",
                    "tooltip": "Nothing unread"
                  }
                }
              },
              "out": {
                "title": "Signed out",
                "item": {
                  "hidden": true
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the row in Slack"
              },
              {
                "keys": "up",
                "title": "Move the cursor (down, j, k too; a click sets it)"
              },
              {
                "keys": "r",
                "title": "Reply: the search row becomes the field, Enter sends"
              },
              {
                "keys": "m",
                "title": "Mark the row read"
              },
              {
                "keys": "a",
                "title": "Mark all read (cmd+shift+a too)"
              },
              {
                "keys": "o",
                "title": "Open Slack"
              },
              {
                "keys": "p",
                "title": "Open the Unreads palette"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the row in the browser"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the row's link"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "slack.attention == 0",
                "description": "Nothing addressed to you: off the strip (narrow it to `slack.attention == 0 and slack.channels == 0` to keep the glyph for channels merely unread), muted for anyone who keeps it.",
                "hidden": true,
                "color": "muted"
              },
              {
                "id": "dm",
                "when": "slack.dm \u003e 0",
                "description": "A direct message waits.",
                "urgent": true
              }
            ]
          }
        },
        "store": {
          "tagline": "Your Slack messages and mentions, in the panel and on the bar",
          "category": "integration",
          "features": [
            "Direct messages, mentions and thread replies with avatars and the message; unread channels under them",
            "`enter` opens the message in Slack; reply or mark as read without leaving the panel",
            "A bar item that counts only what is addressed to you, red while a direct message waits; `space` in its popover reads the message, `i` ignores it until a new one arrives",
            "Every channel and conversation you are in, with the topic and member count",
            "Search as you type with Slack's own filters: `from:@name`, `in:#channel`, `has:link`",
            "Set your status, presence and Do Not Disturb from the panel"
          ],
          "permissions": [
            "network",
            "keychain"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-unreads.png",
              "caption": "Unreads: direct messages, mentions and threads addressed to you, then the channels that are only unread"
            },
            {
              "file": "2-unread-detail.png",
              "caption": "The pane: the unread run of the conversation, oldest first"
            },
            {
              "file": "3-status.png",
              "caption": "Status: what is set now, then the presets, Do Not Disturb and presence"
            },
            {
              "file": "4-search.png",
              "caption": "Search Slack: Slack's syntax typed into the panel"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the Slack glyph with the count of what is addressed to you, red while a direct message waits",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: direct messages, mentions and thread replies with the sender, the message and the time, the channels also unread, the keys",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-reply.png",
              "caption": "r turns the search row into a reply field; Enter posts it to the conversation",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the glyph and the count, red while a direct message waits",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open",
              "description": "The conversation in the Slack app, at the message when one is known.",
              "keys": "enter"
            },
            {
              "title": "Reply",
              "description": "The message typed in the bar (the row's argument) posts to the conversation (into the thread for a threaded mention); a one-field form when picked without it.",
              "keys": "cmd+enter"
            },
            {
              "title": "Send a message",
              "description": "In Channels: the message typed in the bar posts to the conversation; a form when picked without it.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Mark as read",
              "description": "Up to the latest message; the count falls at the next refresh.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Open in browser",
              "description": "The web client's archive page.",
              "keys": "cmd+shift+o"
            },
            {
              "title": "Copy link",
              "keys": "cmd+c"
            },
            {
              "title": "Copy text",
              "description": "A found message's text.",
              "keys": "cmd+c"
            },
            {
              "title": "Set status",
              "description": "A preset, with its expiry; on Set a status…, the text, emoji and expiry typed in the bar."
            },
            {
              "title": "Clear status"
            },
            {
              "title": "Do Not Disturb",
              "description": "30 minutes, 1 hour, until tomorrow, or the minutes typed in the bar; End Do Not Disturb while it is on."
            },
            {
              "title": "Set away / Set active"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/slack",
      "tagline": "Your Slack messages and mentions, in the panel and on the bar",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/slack/screenshots/1-unreads-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/1-unreads.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/2-unread-detail-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/2-unread-detail.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/3-status-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/3-status.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/4-search-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/4-search.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover-reply-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover-reply.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/slack/screenshots/1-unreads.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/2-unread-detail.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/3-status.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/4-search.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover-reply.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/slack/screenshots/1-unreads-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/2-unread-detail-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/3-status-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/4-search-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover-reply-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/slack/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "unreads",
          "title": "Unreads",
          "description": "What is addressed to you (direct messages, mentions, thread replies) as a count, hidden at zero, red while a direct message waits; the popover lists them with the sender, the message and the time, the channels that are only unread, and replies, marks read and opens from the keys.",
          "refresh": {
            "every": 120,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 2 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": true,
      "has_readme": true
    },
    {
      "name": "snake",
      "kind": "registry",
      "title": "Snake II",
      "description": "Snake II exactly as the Nokia 3310 plays it, on the phone's own 84 by 48 screen: its menus, nine levels, five mazes, the bonus creatures and the top score with its fireworks. The arrows steer, Enter is Menu and Select, Backspace is C.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M2 9h7v2H2zM7 4h2v7H7zM7 4h6v2H7zM12.5 9.5h1.5V11h-1.5z",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/snake@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/snake",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "snake",
        "title": "Snake II",
        "description": "Snake II exactly as the Nokia 3310 plays it, on the phone's own 84 by 48 screen: its menus, nine levels, five mazes, the bonus creatures and the top score with its fireworks. The arrows steer, Enter is Menu and Select, Backspace is C.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M2 9h7v2H2zM7 4h2v7H7zM7 4h6v2H7zM12.5 9.5h1.5V11h-1.5z",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "tones",
            "label": "Game tones",
            "text": "The buzzer: the click on eating, the pips on a crash, the top score's jingle",
            "description": "The phone's own \"Warning and game tones\". Also flipped with cmd+T on the game.",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "queue_turns",
            "label": "Queue a quick second turn",
            "text": "Keep a second turn pressed within one step (up then left) for the step after",
            "description": "Not the phone: the real 3310 keeps one turn per step and loses a second key that reverses the way the snake last moved, or points the way it is going. On, that key waits one step instead. Off plays exactly as the firmware.",
            "default": true
          }
        ],
        "sync": {
          "phone": "local",
          "best": "max",
          "options": {
            "fields": {
              "level": "latest",
              "maze": "latest"
            }
          }
        },
        "leaderboards": [
          {
            "id": "top",
            "title": "Top score",
            "order": "desc",
            "format": "points",
            "min": 1,
            "max": 100000
          },
          {
            "id": "week",
            "title": "This week",
            "order": "desc",
            "format": "points",
            "period": "week",
            "min": 1,
            "max": 100000
          },
          {
            "id": "level/*",
            "title": "Level {1}",
            "order": "desc",
            "format": "points",
            "min": 1,
            "max": 100000
          }
        ],
        "store": {
          "tagline": "The Nokia 3310's Snake II, pixel for pixel and step for step",
          "category": "fun",
          "features": [
            "Every screen, sprite, maze, speed and sound taken from the real 3310 firmware and checked against it",
            "The 84 by 48 screen drawn pixel for pixel, lit green in the menus as the phone does",
            "The phone's menus: New game, Level, Mazes, Top score, Instructions and Continue",
            "Nine levels, no maze or mazes 1 to 5, and a bonus creature after every five foods",
            "The split second before a crash, so a late turn still saves the snake",
            "The keypad as the phone had it: arrows as 2 4 6 8, `enter` for Menu, `backspace` for C; Escape pauses",
            "Leaderboards for the top score, this week's and each level's; signed in, your top score, level and maze follow you to your other machines and play.cagdas.io"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-play.png",
              "caption": "Level 5, a bonus creature up with its countdown at the top right; unlit, as the phone keeps its backlight in play",
              "cover": [
                401,
                277,
                638,
                313
              ]
            },
            {
              "file": "2-menu.png",
              "caption": "The Snake II menu, lit, as the phone draws it: Continue for the game left paused"
            },
            {
              "file": "3-maze.png",
              "caption": "Maze 2 at level 5: the bulges of the food swallowed ride down the body"
            },
            {
              "file": "4-topscore.png",
              "caption": "The Top score screen, its coins fallen into the cup"
            }
          ],
          "actions": [
            {
              "title": "2 4 6 8",
              "description": "Steer: up, left, right, down. The arrows while playing. 1 3 7 9 turn across the way the snake goes, `*` and `#` turn left and right.",
              "keys": "up, left, right, down"
            },
            {
              "title": "Menu, Select, OK, More",
              "description": "The phone's left soft key. In play it pauses.",
              "keys": "enter"
            },
            {
              "title": "C",
              "description": "Back; in play it pauses. On the Snake II menu it leaves the game.",
              "keys": "backspace"
            },
            {
              "title": "Scroll",
              "description": "The phone's scroll keys: the arrows in a menu, Page Up and Page Down anywhere (they turn the snake left and right in play).",
              "keys": "pageup, pagedown"
            },
            {
              "title": "Game tones",
              "description": "The buzzer on or off.",
              "keys": "cmd+t"
            }
          ],
          "play": true
        },
        "palettes": {
          "snake": {
            "title": "Snake II",
            "kind": "view",
            "description": "The phone's screen. Escape pauses the game and leaves; Continue waits in the menu.",
            "keys": [
              {
                "keys": "up",
                "title": "2 4 6 8 in play (also down, left, right); the scroll keys in a menu"
              },
              {
                "keys": "enter",
                "title": "Menu, Select, OK, More (the left soft key)"
              },
              {
                "keys": "backspace",
                "title": "C: back, or pause in play"
              },
              {
                "keys": "pageup",
                "title": "Scroll up (in play: turn left); Page Down scrolls down (turn right)"
              },
              {
                "keys": "cmd+t",
                "title": "Game tones on or off"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/snake",
      "tagline": "The Nokia 3310's Snake II, pixel for pixel and step for step",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/snake/screenshots/1-play-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/1-play.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/2-menu-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/2-menu.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/3-maze-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/3-maze.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/4-topscore-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/4-topscore.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/snake/screenshots/1-play.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/2-menu.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/3-maze.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/4-topscore.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/snake/screenshots/1-play-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/2-menu-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/3-maze-dark.png",
        "https://pal.cagdas.io/extensions/snake/screenshots/4-topscore-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "snippets",
      "kind": "bundled",
      "title": "Snippets",
      "description": "Short texts you paste by keyword, with the date, the clipboard, the selection and more filled in. Create and edit them in the panel, import or export JSON, and on macOS expand a keyword as you type in any app.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰆐",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/snippets@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/snippets",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "snippets",
        "title": "Snippets",
        "description": "Short texts you paste by keyword, with the date, the clipboard, the selection and more filled in. Create and edit them in the panel, import or export JSON, and on macOS expand a keyword as you type in any app.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰆐",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [],
        "store": {
          "tagline": "Paste short texts by keyword, placeholders filled in",
          "category": "productivity",
          "features": [
            "`enter` pastes the snippet into the app in front, `cmd+c` copies it",
            "Placeholders for the clipboard, the selection, Finder files, the date and time (any format, with offsets like `+1d`) and a uuid",
            "One snippet can include another with `{snippet name=sig}`",
            "Find a snippet by name or keyword; create and edit it in a form",
            "On macOS, type `;sig` in any app to expand it in place, never in terminals or password fields",
            "Import and export as JSON; Raycast's snippets export is read as is"
          ],
          "permissions": [
            "accessibility",
            "input-monitoring"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Snippets by name, the keyword as a tag, the first line as the subtitle; dynamic ones (braces) fill placeholders when pasted"
            },
            {
              "file": "2-detail.png",
              "caption": "cmd+i shows the whole text under its name, the keyword and dynamic as chips"
            },
            {
              "file": "3-actions.png",
              "caption": "Paste into the app in front, copy, edit or delete a snippet"
            },
            {
              "file": "4-form.png",
              "caption": "Create Snippet: a name, a keyword and the text, its placeholders explained under the field"
            }
          ],
          "actions": [
            {
              "title": "Paste",
              "description": "Hides, then pastes the filled text into the app in front.",
              "keys": "enter"
            },
            {
              "title": "Copy",
              "description": "The filled text onto the clipboard.",
              "keys": "cmd+c"
            },
            {
              "title": "Edit",
              "description": "The form, filled in.",
              "keys": "cmd+e"
            },
            {
              "title": "Delete",
              "description": "Asks first.",
              "keys": "ctrl+x"
            },
            {
              "title": "Create snippet",
              "description": "The form, on the Create row.",
              "keys": "enter"
            },
            {
              "title": "Import…",
              "description": "A JSON file's snippets, the ones you already have skipped.",
              "keys": "enter"
            },
            {
              "title": "Export…",
              "description": "Your snippets to a JSON file.",
              "keys": "enter"
            }
          ]
        },
        "links": {
          "paste": {
            "description": "Paste a snippet by name or keyword, placeholders filled",
            "params": {
              "name": {
                "description": "The snippet's name or keyword, case-insensitive",
                "required": true
              },
              "copy": {
                "description": "Copy it instead of pasting",
                "type": "boolean"
              }
            }
          }
        },
        "palettes": {
          "snippets": {
            "title": "Snippets",
            "tier": "primary",
            "kind": "list",
            "description": "Every snippet by name and keyword, plus Create Snippet.",
            "keys": [
              {
                "keys": "enter",
                "title": "Paste into the app in front"
              },
              {
                "keys": "cmd+c",
                "title": "Copy"
              },
              {
                "keys": "cmd+e",
                "title": "Edit"
              },
              {
                "keys": "ctrl+x",
                "title": "Delete"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/snippets",
      "tagline": "Paste short texts by keyword, placeholders filled in",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/snippets/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/4-form-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/4-form.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/snippets/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/4-form.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/snippets/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/snippets/screenshots/4-form-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "paste",
          "url": "pal://snippets/paste?name=\u003cname\u003e",
          "cli": "pal call snippets/paste name=\u003cname\u003e",
          "description": "Paste a snippet by name or keyword, placeholders filled",
          "params": [
            {
              "name": "name",
              "description": "The snippet's name or keyword, case-insensitive",
              "required": true
            },
            {
              "name": "copy",
              "description": "Copy it instead of pasting",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "solitaire",
      "kind": "registry",
      "title": "Solitaire",
      "description": "Klondike on a felt table: drag the cards with the mouse, or play with the arrows and Enter. Draw one or three, unlimited passes and undo; the game and your record are kept.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󱢯",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/solitaire@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/solitaire",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "solitaire",
        "title": "Solitaire",
        "description": "Klondike on a felt table: drag the cards with the mouse, or play with the arrows and Enter. Draw one or three, unlimited passes and undo; the game and your record are kept.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󱢯",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "draw",
            "label": "Draw",
            "description": "Cards turned from the stock at a time. Applies from the next deal.",
            "options": [
              {
                "id": "1",
                "title": "One card"
              },
              {
                "id": "3",
                "title": "Three cards"
              }
            ],
            "default": "1"
          },
          {
            "kind": "boolean",
            "id": "clock",
            "label": "Clock",
            "text": "Show the time while you play",
            "description": "Off hides the running time beside the table. Your time still shows when you win. Also T or ⌘K in the game.",
            "default": true
          }
        ],
        "sync": {
          "state": "local",
          "stats": {
            "fields": {
              "played": "sum",
              "won": "sum"
            }
          },
          "fastest-1": "min",
          "fastest-3": "min",
          "fewest-1": "min",
          "fewest-3": "min"
        },
        "leaderboards": [
          {
            "id": "daily",
            "title": "Daily deal",
            "order": "asc",
            "format": "time",
            "period": "day",
            "min": 10,
            "max": 86400
          },
          {
            "id": "fastest/*",
            "title": "Fastest win, draw {1}",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 86400
          },
          {
            "id": "fewest/*",
            "title": "Fewest moves, draw {1}",
            "order": "asc",
            "format": "moves",
            "min": 52,
            "max": 100000
          }
        ],
        "store": {
          "tagline": "Klondike solitaire with the mouse or the keyboard",
          "category": "fun",
          "features": [
            "Drag cards and runs with the mouse; the piles they can go on light up",
            "Keyboard play with the arrows and `enter`; `enter` twice sends a card where it belongs",
            "Cards glide and flip, and a win bounces them off the foundations",
            "Draw one or three, unlimited passes, and undo with `U` or `backspace`",
            "Finishes by itself once every card is face up",
            "Your moves, time and games won are kept, and the game waits where you left it",
            "A daily deal, the same cards for everyone that day (`Y`); signed in to pal, your record follows you, and wins go on leaderboards: the day's fastest, and the fastest and fewest-move wins at each draw"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-deal.png",
              "caption": "A fresh deal: the cursor on the stock, the moves, the time and the record beside the table"
            },
            {
              "file": "2-game.png",
              "caption": "54 moves in: the cursor takes 4 cards of a run, the title line names them",
              "cover": [
                173,
                270,
                730,
                358
              ]
            },
            {
              "file": "3-carry.png",
              "caption": "Enter picks the run up: it lifts, and the pile it can go on lights up"
            },
            {
              "file": "4-won.png",
              "caption": "Won: every card home, the moves and the time, Enter deals again"
            }
          ],
          "actions": [
            {
              "title": "Pick up, drop",
              "description": "Enter on a card picks it up (with the cards under it, as deep as ↑ reached); Enter on another pile drops them there. On the stock, draws. With the mouse: drag, or click the cards and then the pile.",
              "keys": "enter"
            },
            {
              "title": "Send where it goes",
              "description": "Enter again on the pile the cards came from, or a double-click: to the card's foundation, else to the first pile that takes them.",
              "keys": "enter"
            },
            {
              "title": "Previous pile, next pile",
              "description": "Across the stock, the waste, the foundations and the seven piles, wrapping round. `h` and `l` too.",
              "keys": "left, right"
            },
            {
              "title": "More cards, fewer cards",
              "description": "How deep into a face-up run to take; past it, the row above or below. `k` and `j` too.",
              "keys": "up, down"
            },
            {
              "title": "Draw",
              "description": "From anywhere; turns the waste back over when the stock is out.",
              "keys": "space"
            },
            {
              "title": "Undo",
              "description": "The last move back, or the cards you hold put back.",
              "keys": "u"
            },
            {
              "title": "New game",
              "description": "Asks first mid-game; the game counts as lost.",
              "keys": "n"
            },
            {
              "title": "Daily deal",
              "description": "Today's deal, draw one, the same cards for everyone until midnight UTC; a win goes on the day's board. Asks first mid-game.",
              "keys": "y"
            },
            {
              "title": "Hide the clock",
              "description": "No running time beside the table; again to bring it back.",
              "keys": "t"
            }
          ],
          "play": true
        },
        "palettes": {
          "solitaire": {
            "title": "Solitaire",
            "kind": "view",
            "description": "The table. Escape leaves mid-game; it is there when you come back.",
            "keys": [
              {
                "keys": "enter",
                "title": "Pick up, drop; twice on the same card, send it where it goes; draw on the stock"
              },
              {
                "keys": "left",
                "title": "Previous pile (also right, h, l)"
              },
              {
                "keys": "up",
                "title": "One more card of the run, then the row above (also down, k, j)"
              },
              {
                "keys": "space",
                "title": "Draw (also d)"
              },
              {
                "keys": "u",
                "title": "Undo (also backspace)"
              },
              {
                "keys": "n",
                "title": "New game, after a confirm mid-game"
              },
              {
                "keys": "y",
                "title": "The daily deal, after a confirm mid-game"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/solitaire",
      "tagline": "Klondike solitaire with the mouse or the keyboard",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/solitaire/screenshots/1-deal-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/1-deal.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/2-game-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/2-game.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/3-carry-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/3-carry.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/4-won-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/4-won.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/solitaire/screenshots/1-deal.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/2-game.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/3-carry.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/4-won.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/solitaire/screenshots/1-deal-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/2-game-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/3-carry-dark.png",
        "https://pal.cagdas.io/extensions/solitaire/screenshots/4-won-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "space",
      "kind": "registry",
      "title": "Disk Space",
      "description": "See what fills your disk as a zoomable map of boxes sized by space, with the biggest files and folders listed and cleanup suggestions like caches and old build folders. Everything deleted goes to the Trash after a confirm.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰋊",
          "bg": "cyan"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/space@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/space",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "space",
        "title": "Disk Space",
        "description": "See what fills your disk as a zoomable map of boxes sized by space, with the biggest files and folders listed and cleanup suggestions like caches and old build folders. Everything deleted goes to the Trash after a confirm.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰋊",
            "bg": "cyan"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "disk",
          "space",
          "storage",
          "treemap",
          "cleanup",
          "du"
        ],
        "settings": [
          {
            "kind": "select",
            "id": "sizes",
            "label": "Sizes",
            "description": "What the boxes and rows measure: the blocks a file takes on disk (what deleting it frees; sparse and compressed files are small), or its apparent length.",
            "options": [
              {
                "id": "allocated",
                "title": "On disk (allocated)"
              },
              {
                "id": "apparent",
                "title": "Apparent"
              }
            ],
            "default": "allocated"
          },
          {
            "kind": "select",
            "id": "colour",
            "label": "Colour boxes by",
            "description": "The kind of file (folder, image, video, code, archive, ...), or the place among the siblings with the nested boxes in their parent's hue (the DaisyDisk ring). `c` in the map flips it.",
            "options": [
              {
                "id": "kind",
                "title": "Kind"
              },
              {
                "id": "depth",
                "title": "Depth"
              }
            ],
            "default": "kind"
          },
          {
            "kind": "boolean",
            "id": "cross_devices",
            "label": "Cross into other volumes",
            "text": "Count folders on other file systems (mounted disks, images) under the root",
            "description": "Off, a scan stays on the root's volume, so a scan of Macintosh HD does not walk every mounted disk. macOS firmlinks (/Users, /Applications on the Data volume) are always crossed.",
            "default": false
          },
          {
            "kind": "number",
            "id": "largest",
            "label": "Largest lists",
            "description": "How many rows Largest Files and Largest Folders show.",
            "min": 10,
            "max": 1000,
            "unit": "rows",
            "default": 100
          },
          {
            "kind": "number",
            "id": "stale_days",
            "label": "Stale after",
            "description": "Cleanup Suggestions count a node_modules or target folder, and a download, as stale past this age.",
            "min": 1,
            "max": 365,
            "unit": "days",
            "default": 30
          }
        ],
        "store": {
          "tagline": "See what fills your disk, and clean it up",
          "category": "system",
          "features": [
            "A zoomable map of any folder or volume: `enter` zooms in, `backspace` out, the arrows move around",
            "Fast scans that draw as they run, and reopen instantly next time",
            "The largest files and folders, with Quick Look, reveal and copy path",
            "Cleanup suggestions: caches, stale `node_modules` and `target` folders, Xcode's DerivedData, old downloads",
            "Mark several boxes with `m` and move them to the Trash together, after one confirm"
          ],
          "permissions": [
            "Full Disk Access, for ~/Library/Mail and the like (unreadable folders are counted and named)"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-map.png",
              "caption": "A home folder as a map: every folder a box sized by what it holds and coloured by kind, the list of the biggest beside it"
            },
            {
              "file": "2-zoomed.png",
              "caption": "Zoomed into a project, its build output and node_modules marked: one keystroke sends both to the Trash"
            },
            {
              "file": "3-largest.png",
              "caption": "The largest files anywhere under the root, each with its folder, kind and size; filter to videos or disk images"
            },
            {
              "file": "4-cleanup.png",
              "caption": "Cleanup suggestions: caches, package stores, the Trash, old downloads and stale build folders, each with what it frees and what to know"
            },
            {
              "file": "5-detail.png",
              "caption": "A file's detail (cmd+I): its folder and kind, the size on disk and the apparent size large, when it changed"
            }
          ],
          "actions": [
            {
              "title": "Zoom in / Open",
              "description": "The focused folder becomes the board; a file opens.",
              "keys": "enter"
            },
            {
              "title": "Zoom out",
              "description": "Back up one folder.",
              "keys": "backspace"
            },
            {
              "title": "Focus",
              "description": "The arrows move between boxes by position, Tab by size.",
              "keys": "up, down, left, right, tab"
            },
            {
              "title": "Mark for the trash",
              "description": "Toggles the focused box; the marked total shows in the header.",
              "keys": "m"
            },
            {
              "title": "Move to Trash",
              "description": "The focused box, or every marked one, after a confirm.",
              "keys": "cmd+d"
            },
            {
              "title": "Quick Look, Open, Reveal, Copy path, Info",
              "description": "The file actions.",
              "keys": "space, cmd+o, cmd+enter, cmd+c, i"
            },
            {
              "title": "Rescan",
              "description": "This folder again (the root: everything). While scanning: stop.",
              "keys": "cmd+r"
            }
          ]
        },
        "palettes": {
          "space": {
            "title": "Disk Space",
            "kind": "live",
            "description": "Where to look: your home folder, every mounted volume with its free space, the folders scanned before with their age, and a folder typed in the bar. Enter opens the map.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the map (scans first when there is none)"
              },
              {
                "keys": "cmd+enter",
                "title": "Largest files under it"
              },
              {
                "keys": "cmd+shift+l",
                "title": "Largest folders under it"
              },
              {
                "keys": "cmd+r",
                "title": "Scan again"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Forget the saved scan"
              }
            ]
          },
          "map": {
            "title": "Disk Map",
            "kind": "view",
            "description": "The treemap: the folder's children as boxes, area by size, their own children faintly inside; zoom in and out, mark and trash.",
            "keys": [
              {
                "keys": "enter",
                "title": "Zoom into the focused folder; open a file"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "backspace",
                "title": "Zoom out"
              },
              {
                "keys": "up",
                "title": "Focus the box in that direction (also down, left, right, and hjkl)"
              },
              {
                "keys": "tab",
                "title": "Next box by size (shift+tab back)"
              },
              {
                "keys": "m",
                "title": "Mark or unmark for the trash"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash: the focused box, or every marked one (asks first)"
              },
              {
                "keys": "space",
                "title": "Quick Look (macOS)"
              },
              {
                "keys": "cmd+o",
                "title": "Open"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "i",
                "title": "Info: kind, sizes, count, modified, owner"
              },
              {
                "keys": "cmd+l",
                "title": "Largest files under this folder"
              },
              {
                "keys": "c",
                "title": "Colour by kind or depth"
              },
              {
                "keys": "a",
                "title": "Sizes on disk or apparent"
              },
              {
                "keys": "cmd+r",
                "title": "Rescan this folder; stop a running scan"
              }
            ]
          },
          "largest": {
            "title": "Largest Files",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "description": "The biggest files under the last scanned root (or the root a link names), kind as a tag; a filter by kind.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+y",
                "title": "Quick Look"
              },
              {
                "keys": "cmd+m",
                "title": "Show in the map"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash (asks; marked rows together)"
              }
            ]
          },
          "folders": {
            "title": "Largest Folders",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "description": "The biggest folders under the last scanned root, with their file counts.",
            "keys": [
              {
                "keys": "enter",
                "title": "Show in the map"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+l",
                "title": "Largest files under it"
              },
              {
                "keys": "cmd+c",
                "title": "Copy path"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash (asks)"
              }
            ]
          },
          "cleanup": {
            "title": "Cleanup Suggestions",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "description": "What is usually safe to clear, with its size: user and package caches, Xcode's DerivedData, node_modules and target folders untouched for a month, downloads older than a month, the Trash. Every action asks first and goes to the Trash.",
            "keys": [
              {
                "keys": "enter",
                "title": "Show in the map"
              },
              {
                "keys": "cmd+enter",
                "title": "Reveal in Finder"
              },
              {
                "keys": "cmd+d",
                "title": "Move to Trash (asks); Empty Trash on the Trash row"
              }
            ]
          }
        },
        "links": {
          "scan": {
            "description": "Open the map of a folder, scanning it first when there is no scan",
            "params": {
              "root": {
                "description": "The folder; ~ is expanded. The home folder without it."
              },
              "rescan": {
                "description": "Scan again even when a scan is saved",
                "type": "boolean"
              }
            }
          },
          "largest": {
            "description": "Open the largest files under a folder",
            "params": {
              "root": {
                "description": "The folder; ~ is expanded. The last scanned root without it."
              }
            }
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/space",
      "tagline": "See what fills your disk, and clean it up",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/space/screenshots/1-map-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/1-map.png",
        "https://pal.cagdas.io/extensions/space/screenshots/2-zoomed-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/2-zoomed.png",
        "https://pal.cagdas.io/extensions/space/screenshots/3-largest-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/3-largest.png",
        "https://pal.cagdas.io/extensions/space/screenshots/4-cleanup-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/4-cleanup.png",
        "https://pal.cagdas.io/extensions/space/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/space/screenshots/1-map.png",
        "https://pal.cagdas.io/extensions/space/screenshots/2-zoomed.png",
        "https://pal.cagdas.io/extensions/space/screenshots/3-largest.png",
        "https://pal.cagdas.io/extensions/space/screenshots/4-cleanup.png",
        "https://pal.cagdas.io/extensions/space/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/space/screenshots/1-map-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/2-zoomed-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/3-largest-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/4-cleanup-dark.png",
        "https://pal.cagdas.io/extensions/space/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "scan",
          "url": "pal://space/scan",
          "cli": "pal call space/scan",
          "description": "Open the map of a folder, scanning it first when there is no scan",
          "params": [
            {
              "name": "root",
              "description": "The folder; ~ is expanded. The home folder without it."
            },
            {
              "name": "rescan",
              "description": "Scan again even when a scan is saved",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "largest",
          "url": "pal://space/largest",
          "cli": "pal call space/largest",
          "description": "Open the largest files under a folder",
          "params": [
            {
              "name": "root",
              "description": "The folder; ~ is expanded. The last scanned root without it."
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "speedtest",
      "kind": "registry",
      "title": "Speedtest",
      "description": "Run an internet speed test and watch it fill in: download and upload as they happen, ping and jitter, the server and your provider. Every run is kept in a history with a trend.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰓅",
          "bg": "violet"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/speedtest@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/speedtest",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "speedtest",
        "title": "Speedtest",
        "description": "Run an internet speed test and watch it fill in: download and upload as they happen, ping and jitter, the server and your provider. Every run is kept in a history with a trend.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰓅",
            "bg": "violet"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "select",
            "id": "tool",
            "label": "Tool",
            "description": "Which CLI runs the test. Auto takes Speedtest by Ookla (the only one that reports progress), else speedtest-cli, else fast. `speedtest` on PATH is told apart by its --version.",
            "options": [
              {
                "id": "auto",
                "title": "Auto (Ookla, speedtest-cli, fast)"
              },
              {
                "id": "ookla",
                "title": "Speedtest by Ookla (speedtest)"
              },
              {
                "id": "speedtest-cli",
                "title": "speedtest-cli (Python)"
              },
              {
                "id": "fast",
                "title": "fast (Netflix, fast-cli)"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "text",
            "id": "server",
            "label": "Server id",
            "description": "A speedtest.net server id to test against (`speedtest -L` lists nearby ones); empty picks the nearest. Ignored by fast.",
            "placeholder": "nearest",
            "default": ""
          },
          {
            "kind": "number",
            "id": "keep",
            "label": "Runs to keep",
            "description": "How many finished runs the history holds.",
            "min": 1,
            "max": 200,
            "default": 30
          }
        ],
        "store": {
          "tagline": "An internet speed test you can watch, with a history",
          "category": "system",
          "features": [
            "Uses the speed test tool you have: Speedtest by Ookla, speedtest-cli or fast, and says how to install one",
            "Starts only when you press `enter`; `enter` again stops it",
            "Live download and upload bars with the speed, ping and jitter, the server and your provider",
            "`cmd+enter` copies the result as one line, `cmd+o` opens Ookla's result page",
            "`cmd+h` shows every past run and a trend of the last twenty"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-idle.png",
              "caption": "Opened: the tool found; nothing runs until Enter"
            },
            {
              "file": "2-running.png",
              "caption": "Downloading: the bar fills with Ookla's progress, the figure moves with it"
            },
            {
              "file": "3-done.png",
              "caption": "Done: both figures, ping and jitter, the server and the ISP"
            },
            {
              "file": "4-history.png",
              "caption": "History: the runs, newest first; the pane has a run's figures large, its ISP and its result page"
            },
            {
              "file": "5-trend.png",
              "caption": "The trend: the last runs as bars, download in blue and upload in green"
            },
            {
              "file": "6-no-tool.png",
              "caption": "Nothing installed: the three ways to get a tool"
            }
          ],
          "actions": [
            {
              "title": "Start the test",
              "description": "Runs the tool; while it runs the same key stops it.",
              "keys": "enter"
            },
            {
              "title": "Copy result",
              "description": "Down, up, ping and jitter, the server and the ISP, on one line.",
              "keys": "cmd+enter"
            },
            {
              "title": "Open the result page",
              "description": "Speedtest by Ookla only.",
              "keys": "cmd+o"
            },
            {
              "title": "History",
              "keys": "cmd+h"
            },
            {
              "title": "Remove a run",
              "description": "In the history.",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "speedtest": {
            "title": "Speedtest",
            "kind": "view",
            "on": [
              "show"
            ],
            "description": "The last result and the tool found; Enter runs a test and the view follows it live; Enter again stops it.",
            "keys": [
              {
                "keys": "enter",
                "title": "Start the test (stop it while it runs)"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy the result"
              },
              {
                "keys": "cmd+o",
                "title": "Open the result page (Ookla)"
              },
              {
                "keys": "cmd+h",
                "title": "History"
              }
            ]
          },
          "history": {
            "title": "Speedtest History",
            "kind": "live",
            "remember": false,
            "description": "Finished runs, newest first, with a Trend row that draws the last twenty as bars.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the run (on Trend: show the bars)"
              },
              {
                "keys": "cmd+o",
                "title": "Open the result page"
              },
              {
                "keys": "cmd+d",
                "title": "Remove the run"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/speedtest",
      "tagline": "An internet speed test you can watch, with a history",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/speedtest/screenshots/1-idle-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/1-idle.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/2-running-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/2-running.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/3-done-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/3-done.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/4-history-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/4-history.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/5-trend-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/5-trend.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/6-no-tool-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/6-no-tool.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/speedtest/screenshots/1-idle.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/2-running.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/3-done.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/4-history.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/5-trend.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/6-no-tool.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/speedtest/screenshots/1-idle-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/2-running-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/3-done-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/4-history-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/5-trend-dark.png",
        "https://pal.cagdas.io/extensions/speedtest/screenshots/6-no-tool-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "spotify",
      "kind": "registry",
      "title": "Spotify",
      "description": "Search, play, queue, like and add to playlists on Spotify from the keyboard, with lyrics that follow the song and a bar item that shows the line playing.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z",
          "box": 24,
          "bg": "#1ED760",
          "fg": "#000000"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/spotify@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/spotify",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "spotify",
        "title": "Spotify",
        "description": "Search, play, queue, like and add to playlists on Spotify from the keyboard, with lyrics that follow the song and a bar item that shows the line playing.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z",
            "box": 24,
            "bg": "#1ED760",
            "fg": "#000000"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "text",
            "id": "client_id",
            "label": "Client id",
            "placeholder": "32 hex characters from developer.spotify.com",
            "description": "Your own Spotify app's client id (README: create one at developer.spotify.com with the redirect http://127.0.0.1:27182/callback). No secret is needed: pal signs in with PKCE.",
            "default": ""
          },
          {
            "kind": "number",
            "id": "redirect_port",
            "label": "Redirect port",
            "description": "The port pal listens on for the sign-in redirect; must match the redirect URI registered on the app.",
            "min": 1024,
            "max": 65535,
            "default": 27182
          },
          {
            "kind": "list",
            "id": "pinned",
            "label": "Pinned playlists",
            "placeholder": "A playlist name, or its spotify:playlist: link",
            "description": "Each one is a \"Play \u003cname\u003e\" row at the root.",
            "default": []
          }
        ],
        "palettes": {
          "now-playing": {
            "title": "Lyrics",
            "description": "The track playing with its cover, a ticking progress bar, the state, and lrclib's synced lyrics around the line playing; follows the song while open.",
            "kind": "view",
            "refresh": 5,
            "keys": [
              {
                "keys": "space, enter",
                "title": "Play or pause"
              },
              {
                "keys": "left, right",
                "title": "Seek 10 s back or forward"
              },
              {
                "keys": "up, down",
                "title": "Volume up or down"
              },
              {
                "keys": "l",
                "title": "Like or unlike"
              },
              {
                "keys": "s",
                "title": "Shuffle on or off"
              },
              {
                "keys": "r",
                "title": "Repeat: all, one, off"
              },
              {
                "keys": "q",
                "title": "The queue"
              },
              {
                "keys": "d",
                "title": "Devices"
              },
              {
                "keys": "cmd+right, cmd+left",
                "title": "Next or previous track"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the line playing (the track without lyrics)"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Spotify"
              },
              {
                "keys": "f",
                "title": "Search lrclib when it has no lyrics"
              }
            ]
          },
          "search": {
            "title": "Search Spotify",
            "description": "Tracks, artists, albums, playlists, podcasts and episodes as sections with their cover art.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Play"
              },
              {
                "keys": "cmd+enter",
                "title": "Add to queue (a track); show tracks (a playlist or album)"
              },
              {
                "keys": "cmd+l",
                "title": "Like or unlike a track"
              },
              {
                "keys": "cmd+p",
                "title": "Add a track to the playlist picked in the bar's field"
              },
              {
                "keys": "cmd+s",
                "title": "Play a playlist shuffled"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Spotify"
              },
              {
                "keys": "cmd+c",
                "title": "Copy link"
              }
            ]
          },
          "playlists": {
            "title": "Playlists",
            "description": "Your playlists and the ones you follow; a drill-in lists the tracks and plays from one.",
            "kind": "list",
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Play"
              },
              {
                "keys": "cmd+enter",
                "title": "Show tracks (a playlist); add to queue (a track of one)"
              },
              {
                "keys": "cmd+s",
                "title": "Play shuffled"
              },
              {
                "keys": "cmd+l",
                "title": "Like or unlike a track of a listed playlist"
              },
              {
                "keys": "cmd+p",
                "title": "Add a listed track to the playlist picked in the bar's field"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Spotify"
              },
              {
                "keys": "cmd+c",
                "title": "Copy link"
              }
            ],
            "lazy": true
          },
          "library": {
            "title": "Library",
            "description": "Liked Songs newest first, recently played, and the top tracks and artists of the last weeks, as filters.",
            "kind": "list",
            "ttl": 300,
            "keys": [
              {
                "keys": "tab",
                "title": "Liked Songs, Recently played, Top tracks, Top artists"
              },
              {
                "keys": "enter",
                "title": "Play"
              },
              {
                "keys": "cmd+enter",
                "title": "Add to queue"
              },
              {
                "keys": "cmd+l",
                "title": "Like or unlike"
              },
              {
                "keys": "cmd+p",
                "title": "Add to the playlist picked in the bar's field"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Spotify"
              },
              {
                "keys": "cmd+c",
                "title": "Copy link"
              }
            ],
            "lazy": true
          },
          "devices": {
            "title": "Spotify Devices",
            "description": "Every device Spotify is open on: transfer playback to one, and the volume of the active one (up, down, mute, or a level typed in the bar).",
            "kind": "live",
            "keys": [
              {
                "keys": "enter",
                "title": "Play here (a device); volume up, down, mute (the volume rows); on Set volume…, the level typed in the bar's field"
              },
              {
                "keys": "cmd+enter",
                "title": "Transfer without playing"
              },
              {
                "keys": "cmd+up, cmd+down",
                "title": "Volume of the active device"
              }
            ],
            "lazy": true
          },
          "queue": {
            "title": "Queue",
            "description": "What plays now and what comes next; skip to a row.",
            "kind": "live",
            "remember": false,
            "keys": [
              {
                "keys": "enter",
                "title": "Skip to the row (play or pause on the first)"
              },
              {
                "keys": "cmd+l",
                "title": "Like or unlike"
              },
              {
                "keys": "cmd+p",
                "title": "Add to the playlist picked in the bar's field"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Spotify"
              },
              {
                "keys": "cmd+c",
                "title": "Copy link"
              }
            ],
            "lazy": true
          },
          "commands": {
            "title": "Spotify",
            "description": "Play or pause, next, previous, like, lyrics, sign out, and a Play row per pinned playlist, all root results.",
            "kind": "list",
            "tier": "primary",
            "keys": [
              {
                "keys": "enter",
                "title": "Run"
              },
              {
                "keys": "cmd+s",
                "title": "Play a pinned playlist shuffled"
              },
              {
                "keys": "cmd+o",
                "title": "Open a pinned playlist in Spotify"
              }
            ]
          }
        },
        "states": {
          "playing": {
            "description": "Spotify is playing",
            "kind": "boolean"
          },
          "loaded": {
            "description": "A track is loaded, playing or paused",
            "kind": "boolean"
          }
        },
        "bar": {
          "playing": {
            "title": "Spotify",
            "description": "The track playing (or the lyric line, with \"Lyrics\"), hidden while nothing plays; the popover is the lyrics view in a compact layout with the transport keys and the queue's next two, ticking while it is up.",
            "mocks": {
              "lyrics": {
                "title": "Synced lyric line",
                "item": {
                  "icon": "󰓇",
                  "title": "Your eyes",
                  "tooltip": "Radiohead - Weird Fishes/ Arpeggi (hornet)"
                }
              },
              "track": {
                "title": "No synced lyrics",
                "item": {
                  "icon": "󰓇",
                  "title": "Weird Fishes/ Arpeggi · Radiohead",
                  "tooltip": "Radiohead - Weird Fishes/ Arpeggi (hornet)"
                }
              },
              "held": {
                "title": "Paused, kept on the bar (While a track is loaded)",
                "item": {
                  "icon": "󰓇",
                  "title": "Weird Fishes/ Arpeggi · Radiohead",
                  "color": "muted",
                  "tooltip": "Radiohead - Weird Fishes/ Arpeggi, paused"
                }
              },
              "paused": {
                "title": "Paused or nothing playing",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰓇",
                    "tooltip": "Nothing playing"
                  }
                }
              }
            },
            "refresh": {
              "every": 30,
              "on": [
                "show",
                "wake",
                "network",
                "media"
              ]
            },
            "keys": [
              {
                "keys": "space",
                "title": "Pause or play"
              },
              {
                "keys": "cmd+right",
                "title": "Next track"
              },
              {
                "keys": "cmd+left",
                "title": "Previous track"
              },
              {
                "keys": "right",
                "title": "Seek 10 s forward"
              },
              {
                "keys": "left",
                "title": "Seek 10 s back"
              },
              {
                "keys": "up",
                "title": "Volume up"
              },
              {
                "keys": "down",
                "title": "Volume down"
              },
              {
                "keys": "l",
                "title": "Like or unlike"
              },
              {
                "keys": "s",
                "title": "Shuffle on or off"
              },
              {
                "keys": "r",
                "title": "Repeat all, one, off"
              },
              {
                "keys": "q",
                "title": "Open the queue"
              },
              {
                "keys": "d",
                "title": "Open the devices"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the current line (or the track)"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Spotify"
              }
            ],
            "rules": [
              {
                "id": "paused",
                "when": "spotify.loaded and not spotify.playing",
                "description": "A loaded track that is paused: off the strip, muted for anyone who keeps it.",
                "hidden": true,
                "color": "muted"
              }
            ],
            "settings": [
              {
                "kind": "boolean",
                "id": "lyrics",
                "label": "Lyrics",
                "text": "Show the lyric line playing instead of the track name",
                "description": "Only when lrclib has synced lyrics for the track; the track name otherwise.",
                "default": true
              }
            ]
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Search, play and queue Spotify from the keyboard",
          "category": "media",
          "features": [
            "Search tracks, artists, albums, playlists and podcasts as you type; `enter` plays, `cmd+enter` queues",
            "Like with `cmd+l`, add to a playlist with `cmd+p`, open in Spotify with `cmd+o`",
            "Your playlists, liked songs, recently played, top tracks, devices and the queue",
            "Synced lyrics around the line playing, with the cover, progress and playback on keys",
            "Play, pause, skip and like from the root, plus a row for each pinned playlist",
            "A bar item with the track or the lyric line playing"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-lyrics.png",
              "caption": "The lyrics view: the cover, the progress, the line playing bright among the lines around it"
            },
            {
              "file": "2-search.png",
              "caption": "Search: tracks, artists, albums, playlists and podcasts as sections"
            },
            {
              "file": "3-playlists.png",
              "caption": "Playlists: yours and the followed ones; cmd+enter lists a playlist's tracks"
            },
            {
              "file": "4-library.png",
              "caption": "Library: Liked Songs newest first, the other filters on Tab"
            },
            {
              "file": "5-queue.png",
              "caption": "The queue: what plays now, what comes next, Enter skips to a row"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the lyric line playing beside the Spotify mark",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-track.png",
              "caption": "A track lrclib has no synced lyrics for: the track and the artist in the line's place",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the cover and the track, the bar ticking, the lyrics around the line playing, the transport keys, and the queue's next two",
              "kind": "bar",
              "box": [
                264,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the mark in the icon font, the line as the label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Play",
              "description": "A track, or a playlist, album, artist or show as the context.",
              "keys": "enter"
            },
            {
              "title": "Add to queue",
              "keys": "cmd+enter"
            },
            {
              "title": "Show tracks",
              "description": "A playlist's or album's tracks as a level; Enter plays from there.",
              "keys": "cmd+enter"
            },
            {
              "title": "Play shuffled",
              "keys": "cmd+s"
            },
            {
              "title": "Like",
              "description": "Adds to or removes from Liked Songs.",
              "keys": "cmd+l"
            },
            {
              "title": "Add to playlist",
              "description": "On any track row: the playlist (yours or a collaborative one) picked in the bar's field; a form with the same select from a hotkey.",
              "keys": "cmd+p"
            },
            {
              "title": "Open in Spotify",
              "keys": "cmd+o"
            },
            {
              "title": "Copy link",
              "keys": "cmd+c"
            },
            {
              "title": "Play or pause",
              "description": "In the lyrics view.",
              "keys": "space"
            },
            {
              "title": "Seek back 10 s",
              "keys": "left"
            },
            {
              "title": "Seek forward 10 s",
              "keys": "right"
            },
            {
              "title": "Volume up",
              "keys": "up"
            },
            {
              "title": "Volume down",
              "keys": "down"
            },
            {
              "title": "Shuffle on",
              "keys": "s"
            },
            {
              "title": "Repeat all",
              "description": "Then Repeat one, then off.",
              "keys": "r"
            },
            {
              "title": "Queue",
              "keys": "q"
            },
            {
              "title": "Devices",
              "keys": "d"
            },
            {
              "title": "Copy current line",
              "keys": "cmd+c"
            },
            {
              "title": "Search on lrclib",
              "description": "When lrclib has no lyrics for the track.",
              "keys": "f"
            },
            {
              "title": "Play here",
              "description": "Transfers playback to the device.",
              "keys": "enter"
            },
            {
              "title": "Transfer without playing",
              "keys": "cmd+enter"
            },
            {
              "title": "Set volume",
              "description": "In Devices: the level (0 to 100) typed in the bar, on the active device.",
              "keys": "enter"
            },
            {
              "title": "Skip to it",
              "description": "In the queue: one Next per row ahead.",
              "keys": "enter"
            },
            {
              "title": "Sign in to Spotify",
              "description": "Opens the browser; pal listens on 127.0.0.1 for the redirect."
            },
            {
              "title": "Sign out",
              "description": "Forgets the tokens."
            }
          ]
        },
        "controls": [
          "player"
        ]
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/spotify",
      "tagline": "Search, play and queue Spotify from the keyboard",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/spotify/screenshots/1-lyrics-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/1-lyrics.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/3-playlists-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/3-playlists.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/4-library-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/4-library.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/5-queue-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/5-queue.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar-track-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar-track.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/spotify/screenshots/1-lyrics.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/3-playlists.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/4-library.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/5-queue.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar-track.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/spotify/screenshots/1-lyrics-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/3-playlists-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/4-library-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/5-queue-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar-track-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/spotify/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "playing",
          "title": "Spotify",
          "description": "The track playing (or the lyric line, with \"Lyrics\"), hidden while nothing plays; the popover is the lyrics view in a compact layout with the transport keys and the queue's next two, ticking while it is up.",
          "refresh": {
            "every": 30,
            "on": [
              "show",
              "wake",
              "network",
              "media"
            ]
          },
          "refresh_words": "every 30s, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "ssh",
      "kind": "registry",
      "title": "SSH Hosts",
      "description": "The hosts in your ssh config, one Enter from a terminal running ssh. Run a command on a host, copy the ssh command, or ping it.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰒋",
          "bg": "teal"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/ssh@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/ssh",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "ssh",
        "title": "SSH Hosts",
        "description": "The hosts in your ssh config, one Enter from a terminal running ssh. Run a command on a host, copy the ssh command, or ping it.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰒋",
            "bg": "teal"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "path",
            "id": "config",
            "label": "Config file",
            "description": "The ssh config to read; Include lines in it are followed one level.",
            "pick": "file",
            "default": "~/.ssh/config"
          },
          {
            "kind": "boolean",
            "id": "include_known_hosts",
            "label": "Known hosts",
            "text": "List the names in ~/.ssh/known_hosts too, in a second section",
            "description": "Only hosts you have connected to by name; hashed and numeric entries are skipped.",
            "default": false
          },
          {
            "kind": "select",
            "id": "terminal",
            "label": "Terminal (macOS)",
            "description": "Which terminal Connect opens. Auto picks the first installed of kitty, Ghostty, Alacritty, iTerm2, Terminal. On Linux $TERMINAL, else kitty, foot, alacritty, xterm.",
            "options": [
              {
                "id": "auto",
                "title": "Auto"
              },
              {
                "id": "kitty",
                "title": "kitty"
              },
              {
                "id": "Terminal",
                "title": "Terminal"
              },
              {
                "id": "iTerm2",
                "title": "iTerm2"
              },
              {
                "id": "Ghostty",
                "title": "Ghostty"
              },
              {
                "id": "Alacritty",
                "title": "Alacritty"
              }
            ],
            "default": "auto"
          }
        ],
        "store": {
          "tagline": "Your ssh config's hosts, one Enter from a terminal",
          "category": "developer",
          "features": [
            "Every host in `~/.ssh/config` and its included files, one section per file",
            "Each row says user@address, with the port and the jump host as tags; its detail (`cmd+i`) the same as a page",
            "`enter` opens a terminal running ssh, or runs a command you typed in the bar",
            "`cmd+shift+c` copies the ssh command, `cmd+shift+j` the jump-host form for a machine without your config",
            "`cmd+p` pings the host and shows the round trip",
            "Optionally the hosts from `known_hosts` too"
          ],
          "permissions": [
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-hosts.png",
              "caption": "Hosts sectioned by the file they came from, user@host under each name, the port and a jump host as tags"
            },
            {
              "file": "2-search.png",
              "caption": "From the root, a host's real name finds its alias: example finds the four hosts under example.com"
            },
            {
              "file": "3-actions.png",
              "caption": "Connect on Enter; copy the host, the ssh command or its -J form through the jump host; ping"
            },
            {
              "file": "4-ping.png",
              "caption": "Ping sends one echo and shows the round trip as a toast"
            },
            {
              "file": "5-detail.png",
              "caption": "A host's detail (cmd+I): its name and file on top, the jump host as a chip, the ssh command, then HostName, User and Port"
            }
          ],
          "actions": [
            {
              "title": "Connect",
              "description": "A terminal window running ssh \u003chost\u003e; the bar takes an optional command first (blank: a shell), run over ssh -t and kept open until Enter.",
              "keys": "enter"
            },
            {
              "title": "Copy host",
              "keys": "cmd+c"
            },
            {
              "title": "Copy ssh command",
              "description": "ssh \u003chost\u003e.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy ssh -J command",
              "description": "ssh -J \u003cjump\u003e \u003chost\u003e, on a host with a ProxyJump.",
              "keys": "cmd+shift+j"
            },
            {
              "title": "Ping",
              "description": "One echo to the HostName; the round trip as a toast.",
              "keys": "cmd+p"
            }
          ]
        },
        "palettes": {
          "ssh": {
            "title": "SSH Hosts",
            "tier": "primary",
            "kind": "list",
            "description": "Every Host in your ssh config, and what it connects to.",
            "keys": [
              {
                "keys": "enter",
                "title": "Connect in a terminal (a command typed in the bar runs there; blank is a shell)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the host name"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the ssh command"
              },
              {
                "keys": "cmd+shift+j",
                "title": "Copy the ssh -J command (a ProxyJump host)"
              },
              {
                "keys": "cmd+p",
                "title": "Ping"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/ssh",
      "tagline": "Your ssh config's hosts, one Enter from a terminal",
      "category": "developer",
      "screenshots": [
        "https://pal.cagdas.io/extensions/ssh/screenshots/1-hosts-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/1-hosts.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/4-ping-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/4-ping.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/ssh/screenshots/1-hosts.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/4-ping.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/ssh/screenshots/1-hosts-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/4-ping-dark.png",
        "https://pal.cagdas.io/extensions/ssh/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "states",
      "kind": "bundled",
      "title": "States",
      "description": "Named values your setup can react to: the ones you declare, built-ins like the hour, the front app and the network, and what extensions publish. Set one by hand for a while, reset it, or declare a new one.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰓹",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/states@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/states",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "states",
        "title": "States",
        "description": "Named values your setup can react to: the ones you declare, built-ins like the hour, the front app and the network, and what extensions publish. Set one by hand for a while, reset it, or declare a new one.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰓹",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "state",
          "states",
          "variable",
          "working"
        ],
        "store": {
          "tagline": "See, set and declare the named states your setup reacts to",
          "category": "system",
          "features": [
            "Every state with its live value and where it comes from: set by hand, its expression, an extension, the default",
            "Hold one true or false for 15 minutes, an hour, three hours or until tomorrow, or type any value and duration",
            "New state adds one to your config file with an expression, a default and a description",
            "A bar item that shows while a state is held by hand, with the time left"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Every state with its value; the glyph says which layer answers (its expression, held by hand with the time left, an extension, built in)"
            },
            {
              "file": "2-held.png",
              "caption": "Tab steps through the filters: held by hand, yours, what extensions publish, the built-ins"
            },
            {
              "file": "3-actions.png",
              "caption": "Set a state for an hour, three, until tomorrow or a value typed, reset it, or remove it from the config"
            },
            {
              "file": "4-new.png",
              "caption": "New state writes [states.\u003cname\u003e] to the config: a name, an expression over the others, a default"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar only while a state is held by hand: its name and the time left",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-two.png",
              "caption": "Two held: the soonest to run out first, the count after it",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the palette: every state with its value; Enter flips one, ⌘R resets it",
              "kind": "bar",
              "box": [
                334,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the state and the time left on amber",
              "kind": "bar"
            }
          ]
        },
        "palettes": {
          "states": {
            "title": "States",
            "description": "Every state with its value and source; set one by hand, reset it, declare a new one.",
            "kind": "live",
            "tier": "normal",
            "keywords": [
              "state",
              "variable",
              "working"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Toggle a boolean, or set the typed value"
              },
              {
                "keys": "cmd+r",
                "title": "Reset the manual value"
              },
              {
                "keys": "cmd+backspace",
                "title": "Remove the declaration from the config"
              }
            ]
          }
        },
        "bar": {
          "forced": {
            "title": "Held states",
            "description": "The states set by hand, with the time left on the soonest to expire; hidden while none is. A click opens the palette.",
            "refresh": {
              "every": 60,
              "on": [
                "state:*"
              ]
            },
            "mocks": {
              "one": {
                "title": "One state held for a while",
                "item": {
                  "icon": "󰓹",
                  "title": "working · 2 h 40 m",
                  "color": "amber",
                  "tooltip": "working = true, set by hand, 2 h 40 m left"
                }
              },
              "two": {
                "title": "Two states held",
                "item": {
                  "icon": "󰓹",
                  "title": "working · 40 m",
                  "badge": 2,
                  "color": "amber",
                  "tooltip": "working = true (40 m), deep = true"
                }
              }
            }
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/states",
      "tagline": "See, set and declare the named states your setup reacts to",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/states/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/states/screenshots/2-held-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/2-held.png",
        "https://pal.cagdas.io/extensions/states/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/states/screenshots/4-new-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/4-new.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar-two-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar-two.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/states/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/states/screenshots/2-held.png",
        "https://pal.cagdas.io/extensions/states/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/states/screenshots/4-new.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar-two.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/states/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/2-held-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/4-new-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar-two-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/states/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "forced",
          "title": "Held states",
          "description": "The states set by hand, with the time left on the soonest to expire; hidden while none is. A click opens the palette.",
          "refresh": {
            "every": 60,
            "on": [
              "state:*"
            ]
          },
          "refresh_words": "every 1 min"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": false
    },
    {
      "name": "stats",
      "kind": "registry",
      "title": "Stats",
      "description": "CPU, memory, disk, network and load on the bar, each item hidden until it has something to say, with a popover of the breakdown and a sparkline of the last few minutes. The same numbers as a list in the panel.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰄧",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/stats@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/stats",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "stats",
        "title": "Stats",
        "description": "CPU, memory, disk, network and load on the bar, each item hidden until it has something to say, with a popover of the breakdown and a sparkline of the last few minutes. The same numbers as a list in the panel.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰄧",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "stats",
          "cpu",
          "memory",
          "ram",
          "disk",
          "network",
          "load",
          "top",
          "htop"
        ],
        "settings": [
          {
            "kind": "number",
            "id": "interval",
            "label": "Sampling interval",
            "description": "Seconds between samples; the bar items, their popovers and the sparklines follow it. A sample costs about 5 ms (the process table, 20 ms, is read every 10 s and every tick while a popover is open).",
            "min": 1,
            "max": 60,
            "step": 1,
            "unit": "s",
            "default": 3
          },
          {
            "kind": "list",
            "id": "disk_hide",
            "label": "Hidden volumes",
            "description": "Mount points or volume names to leave out of the disk item and the palette (a backup disk that is always nearly full).",
            "placeholder": "/Volumes/Backup",
            "default": []
          }
        ],
        "store": {
          "tagline": "CPU, memory, disk, network and load: quiet until they matter",
          "category": "system",
          "features": [
            "Five bar items that appear only when it counts: CPU from 70%, memory from 80%, a nearly full disk, a busy network, high load",
            "Popovers with the breakdown: per-core bars, memory segments, every volume and interface, the busiest processes",
            "Kill a runaway process from its popover, after a confirm",
            "A sparkline of the last three minutes in every popover and in the list's detail pane",
            "Choose what each bar item shows: a percentage, a sparkline, per-core bars, the busiest process, free space or rates",
            "The same numbers as a list: `enter` copies a value; open Activity Monitor or reveal a volume in Finder"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "One row per fact, the value as the name: a build running, the CPU amber, its last three minutes in the detail pane"
            },
            {
              "file": "2-memory.png",
              "caption": "Memory as Activity Monitor counts it: app, wired, compressed and cached, the pressure and the swap"
            },
            {
              "file": "3-volumes.png",
              "caption": "Every volume by name with its free space; the detail says free, used and in all large. Enter copies the mount point, cmd+r reveals it"
            },
            {
              "file": "4-process.png",
              "caption": "The busiest and the largest processes: copy the pid, open Activity Monitor, or kill one after a question"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar only while the CPU is busy: the share, amber from 70%",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-spark.png",
              "caption": "The sparkline label: the last eight samples as block glyphs, a build starting",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-pinned.png",
              "caption": "Pinned past 90%: red, with the process behind it",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: every core's share and the busiest processes, x kills one after asking",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-pinned.png",
              "caption": "An export pinning every core: ffmpeg on top, x kills it after asking",
              "kind": "bar",
              "box": [
                364,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the chip glyph and the share on an amber label",
              "kind": "bar"
            }
          ]
        },
        "palettes": {
          "stats": {
            "title": "Stats",
            "kind": "live",
            "description": "CPU, load, memory, swap, every volume, every interface, the busiest and largest processes, uptime: one row each, the value as the name, Enter copies it.",
            "keywords": [
              "stats",
              "top",
              "usage"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the value (the mount point of a volume, the address of an interface, the pid of a process)"
              },
              {
                "keys": "cmd+o",
                "title": "Open Activity Monitor (the Processes palette on Linux)"
              },
              {
                "keys": "cmd+p",
                "title": "Open the row's bar popover"
              },
              {
                "keys": "cmd+r",
                "title": "Reveal a volume in Finder"
              },
              {
                "keys": "cmd+a",
                "title": "All addresses (the Network palette)"
              },
              {
                "keys": "cmd+backspace",
                "title": "Kill a process (asks first)"
              }
            ]
          }
        },
        "states": {
          "cpu": {
            "description": "CPU share, percent, over the last sample",
            "kind": "number"
          },
          "cpu_top": {
            "description": "The busiest process's name",
            "kind": "string"
          },
          "cores": {
            "description": "Logical cores",
            "kind": "number"
          },
          "memory": {
            "description": "Memory used, percent (app + wired + compressed on macOS; total less available on Linux)",
            "kind": "number"
          },
          "memory_pressure": {
            "description": "The kernel's memory pressure: normal, warn, critical",
            "kind": "string"
          },
          "swap": {
            "description": "Swap used, percent of the swap total; 0 without swap",
            "kind": "number"
          },
          "disk": {
            "description": "The startup volume used, percent",
            "kind": "number"
          },
          "disk_free": {
            "description": "The startup volume's free space, GB",
            "kind": "number"
          },
          "disk_worst": {
            "description": "The fullest writable volume, percent used",
            "kind": "number"
          },
          "net_down": {
            "description": "Bytes in per second over the physical links, in KB/s",
            "kind": "number"
          },
          "net_up": {
            "description": "Bytes out per second over the physical links, in KB/s",
            "kind": "number"
          },
          "load1": {
            "description": "The 1 minute load average",
            "kind": "number"
          },
          "load5": {
            "description": "The 5 minute load average",
            "kind": "number"
          },
          "load15": {
            "description": "The 15 minute load average",
            "kind": "number"
          }
        },
        "links": {
          "cpu": {
            "description": "Open the CPU popover, or the Stats palette on the processor rows",
            "params": {
              "palette": {
                "description": "The palette instead of the popover",
                "type": "boolean"
              }
            }
          },
          "memory": {
            "description": "Open the Memory popover, or the palette on the memory rows",
            "params": {
              "palette": {
                "description": "The palette instead of the popover",
                "type": "boolean"
              }
            }
          },
          "disk": {
            "description": "Open the Disk popover, or the palette on the volumes",
            "params": {
              "palette": {
                "description": "The palette instead of the popover",
                "type": "boolean"
              }
            }
          },
          "network": {
            "description": "Open the Network popover, or the palette on the interfaces",
            "params": {
              "palette": {
                "description": "The palette instead of the popover",
                "type": "boolean"
              }
            }
          },
          "load": {
            "description": "Open the Load popover, or the palette on the processor rows",
            "params": {
              "palette": {
                "description": "The palette instead of the popover",
                "type": "boolean"
              }
            }
          }
        },
        "bar": {
          "cpu": {
            "title": "CPU",
            "description": "The CPU share over the last sample. Hidden by its rules under 70%, amber from there, red from 90%; `show = \"always\"` keeps it on the strip muted, or edit the `quiet` rule to keep it in colour. The popover: the share and load, a sparkline of the last three minutes, one bar per core, the five busiest processes with a Kill key.",
            "refresh": {
              "every": 60,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "idle": {
                "title": "Idle, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰘚",
                    "title": "12%",
                    "tooltip": "CPU 12% · 18 cores · load 2.1 · busiest kitty 4%"
                  }
                }
              },
              "busy": {
                "title": "Busy",
                "item": {
                  "icon": "󰘚",
                  "title": "78%",
                  "color": "amber",
                  "tooltip": "CPU 78% · 18 cores · load 14.2 · busiest node 310%"
                }
              },
              "critical": {
                "title": "Pinned",
                "item": {
                  "icon": "󰘚",
                  "title": "97% · ffmpeg",
                  "color": "red",
                  "tooltip": "CPU 97% · 18 cores · load 22.8 · busiest ffmpeg 1640%"
                }
              },
              "spark": {
                "title": "The sparkline label",
                "item": {
                  "icon": "󰘚",
                  "title": "▂▂▃▅▇▇▆▅",
                  "color": "amber",
                  "tooltip": "CPU 74% · 18 cores"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open Activity Monitor (the Processes palette on Linux)"
              },
              {
                "keys": "x",
                "title": "Kill the focused process (asks first)"
              },
              {
                "keys": "c",
                "title": "Copy the share"
              },
              {
                "keys": "p",
                "title": "Open the Processes palette"
              },
              {
                "keys": "s",
                "title": "Open the Stats palette"
              },
              {
                "keys": "up / down",
                "title": "Move between the processes"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "stats.cpu \u003c 70",
                "description": "Under 70%: nothing to say.",
                "hidden": true
              },
              {
                "id": "high",
                "when": "stats.cpu \u003e= 70",
                "description": "Busy.",
                "color": "amber"
              },
              {
                "id": "critical",
                "when": "stats.cpu \u003e= 90",
                "description": "Pinned.",
                "color": "red"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "label",
                "label": "Label",
                "description": "What the strip says: the share, a sparkline of the last eight samples, one bar per core, or the share and the busiest process.",
                "options": [
                  {
                    "id": "percent",
                    "title": "42%"
                  },
                  {
                    "id": "spark",
                    "title": "▂▃▅▇▆ (sparkline)"
                  },
                  {
                    "id": "bars",
                    "title": "▁▃▇▂ (one bar per core)"
                  },
                  {
                    "id": "top",
                    "title": "42% · node"
                  }
                ],
                "default": "percent"
              }
            ]
          },
          "memory": {
            "title": "Memory",
            "description": "Memory used as Activity Monitor counts it (app + wired + compressed on macOS, total less available on Linux). Hidden under 80% while the kernel reports no pressure; amber from 80% or under pressure, red from 90% or critical pressure. The popover: the segments (app, wired, compressed, cached, free), the swap, a sparkline, the five largest processes with a Kill key.",
            "refresh": {
              "every": 60,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "idle": {
                "title": "Room to spare, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰍛",
                    "title": "63%",
                    "tooltip": "Memory 24.2 GB of 38.7 GB · pressure normal · swap 3.4 GB"
                  }
                }
              },
              "busy": {
                "title": "Filling up",
                "item": {
                  "icon": "󰍛",
                  "title": "84%",
                  "color": "amber",
                  "tooltip": "Memory 32.5 GB of 38.7 GB · pressure warn · swap 3.9 GB"
                }
              },
              "critical": {
                "title": "Under pressure",
                "item": {
                  "icon": "󰍛",
                  "title": "36.1 GB",
                  "color": "red",
                  "tooltip": "Memory 36.1 GB of 38.7 GB · pressure critical · swap 4.0 GB"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open Activity Monitor (the Processes palette on Linux)"
              },
              {
                "keys": "x",
                "title": "Kill the focused process (asks first)"
              },
              {
                "keys": "c",
                "title": "Copy the usage"
              },
              {
                "keys": "p",
                "title": "Open the Processes palette"
              },
              {
                "keys": "s",
                "title": "Open the Stats palette"
              },
              {
                "keys": "up / down",
                "title": "Move between the processes"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "stats.memory \u003c 80 and stats.memory_pressure == 'normal'",
                "description": "Under 80% and no pressure: nothing to say.",
                "hidden": true
              },
              {
                "id": "high",
                "when": "stats.memory \u003e= 80 or stats.memory_pressure == 'warn'",
                "description": "Filling up, or the kernel says so.",
                "color": "amber"
              },
              {
                "id": "critical",
                "when": "stats.memory \u003e= 90 or stats.memory_pressure == 'critical'",
                "description": "Nearly out, or critical pressure.",
                "color": "red"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "label",
                "label": "Label",
                "options": [
                  {
                    "id": "percent",
                    "title": "63%"
                  },
                  {
                    "id": "used",
                    "title": "24.2 GB"
                  },
                  {
                    "id": "free",
                    "title": "14.4 GB free"
                  },
                  {
                    "id": "spark",
                    "title": "▂▃▅▇▆ (sparkline)"
                  }
                ],
                "default": "percent"
              }
            ]
          },
          "disk": {
            "title": "Disk",
            "description": "The startup volume's free space. Hidden while it has room; amber past 85% used or under 20 GB free, red past 95% or under 5 GB, on any writable volume. The popover: every volume with its bar, free space and mount point; Enter reveals the focused one in Finder.",
            "refresh": {
              "every": 60,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "idle": {
                "title": "Room, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰋊",
                    "title": "1.5 TB",
                    "tooltip": "Macintosh HD · 392 GB of 1.9 TB used · 1.5 TB free · 2 more volumes"
                  }
                }
              },
              "filling": {
                "title": "Filling up",
                "item": {
                  "icon": "󰋊",
                  "title": "18.4 GB",
                  "color": "amber",
                  "tooltip": "Macintosh HD · 226 GB of 245 GB used · 18.4 GB free"
                }
              },
              "full": {
                "title": "Nearly full",
                "item": {
                  "icon": "󰋊",
                  "title": "97%",
                  "color": "red",
                  "tooltip": "Macintosh HD · 238 GB of 245 GB used · 4.1 GB free"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Reveal the focused volume in Finder"
              },
              {
                "keys": "c",
                "title": "Copy its mount point"
              },
              {
                "keys": "s",
                "title": "Open the Stats palette"
              },
              {
                "keys": "up / down",
                "title": "Move between the volumes"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "stats.disk_free \u003e 20 and stats.disk_worst \u003c 85",
                "description": "Room on every volume: nothing to say.",
                "hidden": true
              },
              {
                "id": "filling",
                "when": "stats.disk_free \u003c= 20 or stats.disk_worst \u003e= 85",
                "description": "Filling up.",
                "color": "amber"
              },
              {
                "id": "full",
                "when": "stats.disk_free \u003c= 5 or stats.disk_worst \u003e= 95",
                "description": "Nearly full.",
                "color": "red"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "label",
                "label": "Label",
                "description": "The startup volume's figure; the popover has every volume.",
                "options": [
                  {
                    "id": "percent",
                    "title": "19%"
                  },
                  {
                    "id": "free",
                    "title": "1.5 TB (free)"
                  },
                  {
                    "id": "used",
                    "title": "392 GB (used)"
                  }
                ],
                "default": "free"
              }
            ]
          },
          "network": {
            "title": "Network",
            "description": "Bytes in and out per second over the physical links (tunnels ride on one of them and are not counted twice). Hidden under 1 MB/s either way, blue past 10 MB/s. The popover: the two rates, a sparkline of both, every interface with its kind, SSID, address and rates; Enter opens the Network palette for every address.",
            "refresh": {
              "every": 60,
              "on": [
                "wake",
                "network"
              ]
            },
            "mocks": {
              "idle": {
                "title": "Quiet, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰓢",
                    "title": "↓12K ↑3K",
                    "tooltip": "↓ 12 KB/s ↑ 3.1 KB/s · en0 Wi-Fi Zaxxon 192.168.1.23"
                  }
                }
              },
              "download": {
                "title": "A download",
                "item": {
                  "icon": "󰓢",
                  "title": "↓24.6M ↑210K",
                  "tooltip": "↓ 24.6 MB/s ↑ 210 KB/s · en0 Wi-Fi Zaxxon 192.168.1.23"
                }
              },
              "busy": {
                "title": "Saturated",
                "item": {
                  "icon": "󰓢",
                  "title": "↓94.1M ↑1.2M",
                  "color": "blue",
                  "tooltip": "↓ 94.1 MB/s ↑ 1.2 MB/s · en7 192.168.1.40"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "All addresses (the Network palette)"
              },
              {
                "keys": "c",
                "title": "Copy the focused interface's address"
              },
              {
                "keys": "s",
                "title": "Open the Stats palette"
              },
              {
                "keys": "up / down",
                "title": "Move between the interfaces"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "stats.net_down \u003c 1024 and stats.net_up \u003c 1024",
                "description": "Under 1 MB/s either way: nothing to say.",
                "hidden": true
              },
              {
                "id": "busy",
                "when": "stats.net_down \u003e= 10240 or stats.net_up \u003e= 10240",
                "description": "Past 10 MB/s.",
                "color": "blue"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "label",
                "label": "Label",
                "options": [
                  {
                    "id": "rate",
                    "title": "↓1.2M ↑80K"
                  },
                  {
                    "id": "down",
                    "title": "↓1.2M"
                  },
                  {
                    "id": "spark",
                    "title": "▂▃▅▇▆ (download sparkline)"
                  }
                ],
                "default": "rate"
              }
            ]
          },
          "load": {
            "title": "Load",
            "description": "The 1 minute load average. Hidden under the core count, amber from there, red from twice it. The popover: the three averages as tiles, the per-core figure, a sparkline.",
            "refresh": {
              "every": 60,
              "on": [
                "wake"
              ]
            },
            "mocks": {
              "idle": {
                "title": "Fine, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰓅",
                    "title": "3.26",
                    "tooltip": "Load 3.26 3.25 2.91 · 18 cores"
                  }
                }
              },
              "high": {
                "title": "Past the cores",
                "item": {
                  "icon": "󰓅",
                  "title": "21.4",
                  "color": "amber",
                  "tooltip": "Load 21.4 14.2 8.1 · 18 cores"
                }
              },
              "critical": {
                "title": "Twice the cores",
                "item": {
                  "icon": "󰓅",
                  "title": "38.9 31.2 22.5",
                  "color": "red",
                  "tooltip": "Load 38.9 31.2 22.5 · 18 cores"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open Activity Monitor (the Processes palette on Linux)"
              },
              {
                "keys": "c",
                "title": "Copy the three averages"
              },
              {
                "keys": "s",
                "title": "Open the Stats palette"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "stats.load1 \u003c stats.cores",
                "description": "Under the core count: nothing to say.",
                "hidden": true
              },
              {
                "id": "high",
                "when": "stats.load1 \u003e= stats.cores",
                "description": "More runnable work than cores.",
                "color": "amber"
              },
              {
                "id": "critical",
                "when": "stats.load1 \u003e= stats.cores * 2",
                "description": "Twice the cores.",
                "color": "red"
              }
            ],
            "settings": [
              {
                "kind": "select",
                "id": "label",
                "label": "Label",
                "options": [
                  {
                    "id": "one",
                    "title": "3.26 (1 min)"
                  },
                  {
                    "id": "three",
                    "title": "3.26 3.25 2.91"
                  }
                ],
                "default": "one"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/stats",
      "tagline": "CPU, memory, disk, network and load: quiet until they matter",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/stats/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/2-memory-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/2-memory.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/3-volumes-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/3-volumes.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/4-process-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/4-process.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-pinned-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-pinned.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-spark-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-spark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover-pinned-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover-pinned.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/stats/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/2-memory.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/3-volumes.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/4-process.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-pinned.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-spark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover-pinned.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/stats/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/2-memory-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/3-volumes-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/4-process-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-pinned-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-spark-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover-pinned-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/stats/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "cpu",
          "title": "CPU",
          "description": "The CPU share over the last sample. Hidden by its rules under 70%, amber from there, red from 90%; `show = \"always\"` keeps it on the strip muted, or edit the `quiet` rule to keep it in colour. The popover: the share and load, a sparkline of the last three minutes, one bar per core, the five busiest processes with a Kill key.",
          "refresh": {
            "every": 60,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 1 min, on wake"
        },
        {
          "id": "memory",
          "title": "Memory",
          "description": "Memory used as Activity Monitor counts it (app + wired + compressed on macOS, total less available on Linux). Hidden under 80% while the kernel reports no pressure; amber from 80% or under pressure, red from 90% or critical pressure. The popover: the segments (app, wired, compressed, cached, free), the swap, a sparkline, the five largest processes with a Kill key.",
          "refresh": {
            "every": 60,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 1 min, on wake"
        },
        {
          "id": "disk",
          "title": "Disk",
          "description": "The startup volume's free space. Hidden while it has room; amber past 85% used or under 20 GB free, red past 95% or under 5 GB, on any writable volume. The popover: every volume with its bar, free space and mount point; Enter reveals the focused one in Finder.",
          "refresh": {
            "every": 60,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 1 min, on wake"
        },
        {
          "id": "network",
          "title": "Network",
          "description": "Bytes in and out per second over the physical links (tunnels ride on one of them and are not counted twice). Hidden under 1 MB/s either way, blue past 10 MB/s. The popover: the two rates, a sparkline of both, every interface with its kind, SSID, address and rates; Enter opens the Network palette for every address.",
          "refresh": {
            "every": 60,
            "on": [
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, on wake, when the network is back"
        },
        {
          "id": "load",
          "title": "Load",
          "description": "The 1 minute load average. Hidden under the core count, amber from there, red from twice it. The popover: the three averages as tiles, the per-core figure, a sparkline.",
          "refresh": {
            "every": 60,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 1 min, on wake"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "cpu",
          "url": "pal://stats/cpu",
          "cli": "pal call stats/cpu",
          "description": "Open the CPU popover, or the Stats palette on the processor rows",
          "params": [
            {
              "name": "palette",
              "description": "The palette instead of the popover",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "memory",
          "url": "pal://stats/memory",
          "cli": "pal call stats/memory",
          "description": "Open the Memory popover, or the palette on the memory rows",
          "params": [
            {
              "name": "palette",
              "description": "The palette instead of the popover",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "disk",
          "url": "pal://stats/disk",
          "cli": "pal call stats/disk",
          "description": "Open the Disk popover, or the palette on the volumes",
          "params": [
            {
              "name": "palette",
              "description": "The palette instead of the popover",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "network",
          "url": "pal://stats/network",
          "cli": "pal call stats/network",
          "description": "Open the Network popover, or the palette on the interfaces",
          "params": [
            {
              "name": "palette",
              "description": "The palette instead of the popover",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "load",
          "url": "pal://stats/load",
          "cli": "pal call stats/load",
          "description": "Open the Load popover, or the palette on the processor rows",
          "params": [
            {
              "name": "palette",
              "description": "The palette instead of the popover",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "store",
      "kind": "bundled",
      "title": "Store",
      "description": "Browse every extension your registries list, read its description and screenshots, and install it with Enter. Updates lead the list, and marked rows install, update or remove together.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰟇",
          "bg": "teal"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/store@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/store",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "store",
        "title": "Store",
        "description": "Browse every extension your registries list, read its description and screenshots, and install it with Enter. Updates lead the list, and marked rows install, update or remove together.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰟇",
            "bg": "teal"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "Browse, install and update extensions without leaving the panel",
          "category": "system",
          "features": [
            "Opens on three featured extensions and a section per category, each row with its icon, tagline and status (installed, built in, update available); typing searches them all",
            "Narrow to Installed, Updates, a registry, or a category like Developer, Media or Fun",
            "`cmd+i` shows the description, palettes and screenshots, where it comes from and whether it updates itself",
            "`enter` installs (after a confirm), updates, or opens an extension you already have",
            "Mark several rows to install, update or remove them together; `ctrl+x` removes one and keeps its settings",
            "`cmd+r` fetches the registries again; one that does not answer says so above the list"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-browse.png",
              "caption": "The store as it opens: an update that waits, three featured, then a section per category with how each stands"
            },
            {
              "file": "2-detail.png",
              "caption": "cmd+I opens the detail pane: what the extension is and does, its palettes and pictures, where it comes from"
            },
            {
              "file": "3-actions.png",
              "caption": "Install on Enter; the store page and the install command a keystroke away"
            }
          ],
          "actions": [
            {
              "title": "Install",
              "description": "After a confirm; waits for the download and the load, then says how it went.",
              "keys": "enter"
            },
            {
              "title": "Update",
              "description": "On an extension the core has an update for.",
              "keys": "enter"
            },
            {
              "title": "Open",
              "description": "An installed extension's first palette.",
              "keys": "enter"
            },
            {
              "title": "Open store page",
              "description": "The extension's page on pal.cagdas.io, for pal's own registry.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy install command",
              "description": "`pal install \u003cname\u003e` onto the clipboard.",
              "keys": "cmd+c"
            },
            {
              "title": "Remove",
              "description": "One installed from a registry; asks first. Its settings and data stay.",
              "keys": "ctrl+x"
            }
          ]
        },
        "palettes": {
          "store": {
            "title": "Store",
            "tier": "primary",
            "kind": "input",
            "description": "Every listed extension, narrowed by the query and the filter; Enter installs, updates or opens.",
            "keys": [
              {
                "keys": "enter",
                "title": "Install, update, or open"
              },
              {
                "keys": "cmd+enter",
                "title": "Open store page"
              },
              {
                "keys": "cmd+c",
                "title": "Copy install command"
              },
              {
                "keys": "ctrl+x",
                "title": "Remove one installed from a registry"
              },
              {
                "keys": "cmd+i",
                "title": "Description, palettes and screenshots"
              },
              {
                "keys": "tab",
                "title": "Next filter: Installed, Updates, Registries, a shelf"
              },
              {
                "keys": "cmd+r",
                "title": "Fetch every registry again"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/store",
      "tagline": "Browse, install and update extensions without leaving the panel",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/store/screenshots/1-browse-dark.png",
        "https://pal.cagdas.io/extensions/store/screenshots/1-browse.png",
        "https://pal.cagdas.io/extensions/store/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/store/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/store/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/store/screenshots/3-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/store/screenshots/1-browse.png",
        "https://pal.cagdas.io/extensions/store/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/store/screenshots/3-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/store/screenshots/1-browse-dark.png",
        "https://pal.cagdas.io/extensions/store/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/store/screenshots/3-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "sudoku",
      "kind": "registry",
      "title": "Sudoku",
      "description": "Sudoku made on your machine: a daily puzzle in Easy, Medium, Hard and Expert (the same for everyone that day) and a new one whenever you like, graded by the techniques it takes. Notes without switching modes, auto notes, hints that explain in plain words, and every move saved.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰋁",
          "bg": "blue"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/sudoku@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/sudoku",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "sudoku",
        "title": "Sudoku",
        "description": "Sudoku made on your machine: a daily puzzle in Easy, Medium, Hard and Expert (the same for everyone that day) and a new one whenever you like, graded by the techniques it takes. Notes without switching modes, auto notes, hints that explain in plain words, and every move saved.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰋁",
            "bg": "blue"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "puzzle",
          "numbers",
          "daily",
          "logic",
          "grid"
        ],
        "sync": {
          "counts": {
            "fields": {
              "easy": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "flawless": "sum",
                  "ms": "sum"
                }
              },
              "medium": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "flawless": "sum",
                  "ms": "sum"
                }
              },
              "hard": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "flawless": "sum",
                  "ms": "sum"
                }
              },
              "expert": {
                "fields": {
                  "solved": "sum",
                  "clean": "sum",
                  "flawless": "sum",
                  "ms": "sum"
                }
              }
            }
          },
          "best": {
            "fields": {
              "easy": "min",
              "medium": "min",
              "hard": "min",
              "expert": "min"
            }
          },
          "days": {
            "fields": {
              "easy": "union",
              "medium": "union",
              "hard": "union",
              "expert": "union"
            }
          },
          "seeded": "local"
        },
        "leaderboards": [
          {
            "id": "fastest/easy",
            "title": "Fastest easy",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 36000
          },
          {
            "id": "fastest/medium",
            "title": "Fastest medium",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 36000
          },
          {
            "id": "fastest/hard",
            "title": "Fastest hard",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 36000
          },
          {
            "id": "fastest/expert",
            "title": "Fastest expert",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 36000
          },
          {
            "id": "daily/*/*",
            "title": "Daily {1}, {2}",
            "order": "asc",
            "format": "time",
            "min": 10,
            "max": 36000
          }
        ],
        "settings": [
          {
            "kind": "select",
            "id": "difficulty",
            "label": "Opens on",
            "description": "Whose daily the first open shows when nothing is left half-done. ⌘N picks any difficulty either way.",
            "options": [
              {
                "id": "easy",
                "title": "Easy"
              },
              {
                "id": "medium",
                "title": "Medium"
              },
              {
                "id": "hard",
                "title": "Hard"
              },
              {
                "id": "expert",
                "title": "Expert"
              }
            ],
            "default": "medium"
          },
          {
            "kind": "select",
            "id": "check",
            "label": "Checking",
            "description": "Clashes are the same digit twice in a row, column or box. Mistakes also mark a digit that is not the answer, and count them. Also on ⌘K.",
            "options": [
              {
                "id": "conflicts",
                "title": "Show clashes only"
              },
              {
                "id": "mistakes",
                "title": "Show mistakes as you make them"
              }
            ],
            "default": "conflicts"
          },
          {
            "kind": "boolean",
            "id": "clock",
            "label": "Clock",
            "text": "Show the time while you play",
            "description": "Off hides the running time. Your times still count for stats and show when you finish. Also T or ⌘K in the game.",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "auto_notes",
            "label": "Auto notes",
            "text": "Keep every empty cell's notes filled in for me",
            "description": "Each empty cell shows the digits that still fit, updated as you play; you only take out the ones you rule out, and they stay out. Off brings your own notes back. Also C or ⌘K in the game.",
            "default": false
          }
        ],
        "store": {
          "tagline": "Daily sudoku in four difficulties, with notes and hints that explain",
          "category": "fun",
          "features": [
            "A daily puzzle per difficulty, the same on every machine, and a new one any time with `cmd+n`; nothing is fetched",
            "Graded by the techniques it needs, from singles you can spot to X-wings and swordfish",
            "Notes without an extra step: type a second digit into a cell and it keeps both as notes; auto notes on `c`",
            "Hints in three steps: where to look, why in plain words, then the move",
            "A digit-first mode on `d`, undo and redo, and clashes or mistakes marked as you play",
            "A clock you can hide, streaks, best and average times per difficulty, and every past daily by month",
            "Clean solves go on leaderboards, the fastest per difficulty and each daily's own; signed in to a pal account, the stats and streaks follow you to every machine"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-solving.png",
              "caption": "Today's medium, half solved: the digit in focus and its notes lit across the board, the pad's bars"
            },
            {
              "file": "2-hint.png",
              "caption": "A hint: where to look first, then why, and the move on Enter"
            },
            {
              "file": "3-solved.png",
              "caption": "Solved: the time, the streak, Flawless, and today's next daily on Enter",
              "cover": [
                172,
                272,
                844,
                414
              ]
            },
            {
              "file": "4-new.png",
              "caption": "⌘N: today's puzzle or a new one, per difficulty"
            },
            {
              "file": "5-stats.png",
              "caption": "Stats per difficulty: the best, the average, the streak and every solve"
            }
          ],
          "actions": [
            {
              "title": "Hint",
              "description": "Where to look; again for why; again for the move.",
              "keys": "i"
            },
            {
              "title": "Notes mode",
              "description": "Digits write notes instead. Shift with a digit writes one without switching, and a second digit over a placed one makes notes anyway.",
              "keys": "n"
            },
            {
              "title": "Auto notes",
              "description": "Every empty cell shows what still fits; you only take notes out. Again to bring your own back.",
              "keys": "c"
            },
            {
              "title": "Digit first",
              "description": "Pick a digit, then click the cells it goes in. Again to leave.",
              "keys": "d"
            },
            {
              "title": "Fill in notes",
              "description": "Every empty cell gets what fits; notes you wrote are only trimmed. Shift-A clears them.",
              "keys": "a"
            },
            {
              "title": "Undo",
              "description": "Shift-U or ⌘⇧Z redoes.",
              "keys": "u"
            },
            {
              "title": "New game",
              "description": "Today's puzzle or a new one, per difficulty.",
              "keys": "cmd+n"
            },
            {
              "title": "Browse",
              "description": "The dailies by month, and every half-done game.",
              "keys": "cmd+o"
            },
            {
              "title": "Stats",
              "description": "Times, streaks and the history per difficulty.",
              "keys": "cmd+s"
            },
            {
              "title": "Pause",
              "description": "Stops the clock and hides the board.",
              "keys": "p"
            },
            {
              "title": "Hide the clock",
              "description": "No running time on screen; again to bring it back. Times still count.",
              "keys": "t"
            }
          ]
        },
        "palettes": {
          "sudoku": {
            "kind": "view",
            "title": "Sudoku",
            "description": "The game left half-done, else today's daily. Escape leaves at any point; every move is saved.",
            "keys": [
              {
                "keys": "1",
                "title": "Place a digit (1 to 9); a different one over it makes notes"
              },
              {
                "keys": "shift+1",
                "title": "A note (shift or alt with a digit)"
              },
              {
                "keys": "n",
                "title": "Notes mode (or space)"
              },
              {
                "keys": "c",
                "title": "Auto notes"
              },
              {
                "keys": "d",
                "title": "Digit first: pick a digit, click cells"
              },
              {
                "keys": "backspace",
                "title": "Erase"
              },
              {
                "keys": "up",
                "title": "Move (or h j k l)"
              },
              {
                "keys": "i",
                "title": "Hint: where, why, then the move"
              },
              {
                "keys": "u",
                "title": "Undo (shift+u redo)"
              },
              {
                "keys": "cmd+n",
                "title": "New game or today's puzzle"
              },
              {
                "keys": "?",
                "title": "Every key"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/sudoku",
      "tagline": "Daily sudoku in four difficulties, with notes and hints that explain",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/sudoku/screenshots/1-solving-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/1-solving.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/2-hint-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/2-hint.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/3-solved-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/3-solved.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/4-new-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/4-new.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/5-stats-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/5-stats.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/sudoku/screenshots/1-solving.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/2-hint.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/3-solved.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/4-new.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/5-stats.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/sudoku/screenshots/1-solving-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/2-hint-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/3-solved-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/4-new-dark.png",
        "https://pal.cagdas.io/extensions/sudoku/screenshots/5-stats-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "system",
      "kind": "bundled",
      "title": "System",
      "description": "System commands from the keyboard: sleep, lock, restart, shut down, empty the trash, dark mode, volume, brightness, eject, quit every app, clear notifications. Keep the computer awake for a while, until a time or while an app runs, with a countdown on the bar.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰐥",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/system@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/system",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "system",
        "title": "System",
        "description": "System commands from the keyboard: sleep, lock, restart, shut down, empty the trash, dark mode, volume, brightness, eject, quit every app, clear notifications. Keep the computer awake for a while, until a time or while an app runs, with a countdown on the bar.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰐥",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "confirm_destructive",
            "label": "Ask first",
            "text": "Confirm before logging out, restarting, shutting down, emptying the trash or quitting every app",
            "default": true,
            "description": "Log Out, Restart, Shut Down, Empty Trash and Quit All Apps show a confirmation first; off runs them at once."
          },
          {
            "kind": "text",
            "id": "awake_default",
            "label": "Keep awake for",
            "placeholder": "1h",
            "default": "1h",
            "description": "What a bare Keep Awake runs for: 45m, 2h, 1h30m, a clock time like 14:30, or forever."
          },
          {
            "kind": "boolean",
            "id": "awake_display",
            "label": "Display",
            "text": "Keep the display awake too",
            "default": true,
            "description": "On: neither the machine nor the display sleeps (caffeinate -d -i). Off: the display may sleep while the machine stays up, for a download or a build. The row's Display field and the popover's switch override it per run."
          }
        ],
        "store": {
          "tagline": "Sleep, lock, restart, dark mode, volume, keep awake",
          "category": "system",
          "features": [
            "Type `mute`, `sleep` or `power off` at the root to find the command",
            "Only what this machine can do is listed; Empty Trash shows how much is in it, Dark Mode the current look",
            "Keep Awake for `45m`, `2h`, until `14:30` or while an app runs; the bar counts down, and it ends on time even if pal quits",
            "Quit All Apps asks each app the usual way, so unsaved work still prompts; Unhide All Apps and Dismiss Notifications too",
            "Log Out, Restart, Shut Down and Empty Trash ask first (a setting)",
            "Quick Look on what is selected in Finder (macOS)"
          ],
          "permissions": [
            "automation",
            "full-disk-access"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "The commands this machine can run; the appearance and the Trash count on the right"
            },
            {
              "file": "2-root.png",
              "caption": "caffeinate at the root finds Keep Awake: the rows are indexed with their keywords"
            },
            {
              "file": "3-confirm.png",
              "caption": "A destructive command asks first"
            },
            {
              "file": "4-apps.png",
              "caption": "Quit All Apps (asks first), Unhide All Apps, Dismiss Notifications, and Quick Look on what is marked in Finder"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: a coffee and what is left of the run",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-display.png",
              "caption": "The display kept awake too: a monitor mark after the countdown",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the run on a card with the time left and a bar, the presets on the digits, the display switch, Enter allows sleep",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                644
              ]
            },
            {
              "file": "bar-popover-forever.png",
              "caption": "Until turned off: ∞ on the strip and the card; a preset gives it an end",
              "kind": "bar",
              "box": [
                430,
                64,
                840,
                628
              ]
            },
            {
              "file": "bar-popover-field.png",
              "caption": "u opens the field: 45m, 14:30 or forever, then Enter",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                690
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the coffee and the countdown as the label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Run",
              "description": "The command; Log Out, Restart, Shut Down, Empty Trash and Quit All Apps ask first.",
              "keys": "enter"
            },
            {
              "title": "Keep awake",
              "description": "On Keep Awake: for what the bar's field says, else the default; cmd+enter until turned off; cmd+u the form (a time, an app to follow, the display).",
              "keys": "enter"
            },
            {
              "title": "Allow sleep",
              "description": "On the row while a run is on; cmd+d flips whether the display is kept awake too.",
              "keys": "enter"
            }
          ]
        },
        "links": {
          "run": {
            "description": "Run a system command",
            "confirm": true,
            "params": {
              "id": {
                "description": "sleep, lock, logout, restart, shutdown, empty-trash, dark-mode, volume-up, volume-down, volume-mute, brightness-up, brightness-down, dnd, eject-all, show-desktop, keep-awake (the toggle: the default duration, or off), quit-all, unhide-all, dismiss-notifications, quick-look-selection (macOS)",
                "required": true
              }
            }
          },
          "awake": {
            "description": "Keep the machine awake, or let it sleep",
            "params": {
              "for": {
                "description": "How long: 45m, 2h, 1h30m, or a clock time like 14:30, or forever; blank with nothing else toggles (the default duration, or off while on)"
              },
              "until": {
                "description": "The same as for; a clock time reads best here (tomorrow's when today's has passed)"
              },
              "display": {
                "description": "Keep the display awake too (the setting otherwise)",
                "type": "boolean"
              },
              "app": {
                "description": "An app with a window open: the run ends when it quits (caffeinate -w)"
              },
              "off": {
                "description": "Allow sleep now",
                "type": "boolean"
              }
            }
          }
        },
        "palettes": {
          "system": {
            "title": "System",
            "tier": "primary",
            "kind": "live",
            "description": "What this machine can do from here; Keep Awake takes how long in the bar.",
            "keys": [
              {
                "keys": "enter",
                "title": "Run the command; on Keep Awake, for what the bar says (the default when blank); Allow Sleep while a run is on"
              },
              {
                "keys": "cmd+enter",
                "title": "On Keep Awake: until turned off"
              },
              {
                "keys": "cmd+u",
                "title": "On Keep Awake: a form for a time, an app to follow and the display"
              },
              {
                "keys": "cmd+d",
                "title": "On Allow Sleep: keep the display awake too, or let it sleep"
              }
            ]
          }
        },
        "states": {
          "awake": {
            "description": "A keep-awake run is on",
            "kind": "boolean"
          },
          "awake_until": {
            "description": "When the run ends, unix ms; null without an end",
            "kind": "number"
          },
          "awake_left": {
            "description": "Minutes left, rounded up; null without an end",
            "kind": "number"
          },
          "awake_display": {
            "description": "The display is kept awake too",
            "kind": "boolean"
          }
        },
        "bar": {
          "awake": {
            "title": "Keep Awake",
            "description": "A coffee glyph and what is left of the run (∞ without an end), a monitor mark when the display is kept awake too; hidden while off (`show = \"always\"` keeps a muted coffee). The popover: the run on a card with the time left and a bar, the presets as tiles on the digits, the display switch, Allow sleep on Enter; `u` opens a field for a time or a duration.",
            "refresh": {
              "every": 60,
              "on": [
                "wake"
              ]
            },
            "rules": [
              {
                "id": "ending",
                "when": "system.awake and system.awake_left \u003c= 5",
                "description": "Five minutes or less left.",
                "color": "amber"
              }
            ],
            "mocks": {
              "off": {
                "title": "Not kept awake",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰛊",
                    "tooltip": "Not kept awake"
                  }
                }
              },
              "left": {
                "title": "25 minutes left",
                "item": {
                  "icon": "󰛊",
                  "title": "25m",
                  "tooltip": "Awake until 14:55, 25 min left"
                }
              },
              "forever": {
                "title": "Until turned off",
                "item": {
                  "icon": "󰛊",
                  "title": "∞",
                  "tooltip": "Awake until turned off"
                }
              },
              "display": {
                "title": "Display kept awake too",
                "item": {
                  "icon": "󰛊",
                  "title": "1h 59m",
                  "segments": [
                    {
                      "id": "display",
                      "icon": "󰍹",
                      "color": "muted",
                      "tooltip": "Display kept awake too"
                    }
                  ],
                  "tooltip": "Awake until 16:29, 1 h 59 min left, display too"
                }
              },
              "ending": {
                "title": "Under five minutes",
                "item": {
                  "icon": "󰛊",
                  "title": "4m",
                  "color": "amber",
                  "tooltip": "Awake until 14:34, 4 min left"
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Allow sleep (while on); keep awake for the default (while off)"
              },
              {
                "keys": "1",
                "title": "Keep awake for a preset (1 to 5, the tiles)"
              },
              {
                "keys": "d",
                "title": "Keep the display awake too, or let it sleep"
              },
              {
                "keys": "u",
                "title": "A field for a time or a duration: 45m, 14:30, forever, then Enter"
              },
              {
                "keys": "backspace",
                "title": "Allow sleep"
              },
              {
                "keys": "o",
                "title": "Open the System palette"
              }
            ],
            "settings": [
              {
                "kind": "list",
                "id": "presets",
                "label": "Presets",
                "placeholder": "30m, 1h, 2h, forever",
                "default": [
                  "30m",
                  "1h",
                  "2h",
                  "forever"
                ],
                "description": "The durations on the popover's tiles and its digit keys, five at most: durations, clock times, or forever."
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/system",
      "tagline": "Sleep, lock, restart, dark mode, volume, keep awake",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/system/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/system/screenshots/2-root-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/2-root.png",
        "https://pal.cagdas.io/extensions/system/screenshots/3-confirm-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/3-confirm.png",
        "https://pal.cagdas.io/extensions/system/screenshots/4-apps-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/4-apps.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar-display-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar-display.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-field-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-field.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-forever-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-forever.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/system/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/system/screenshots/2-root.png",
        "https://pal.cagdas.io/extensions/system/screenshots/3-confirm.png",
        "https://pal.cagdas.io/extensions/system/screenshots/4-apps.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar-display.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-field.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-forever.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/system/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/2-root-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/3-confirm-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/4-apps-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar-display-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-field-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-forever-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/system/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "awake",
          "title": "Keep Awake",
          "description": "A coffee glyph and what is left of the run (∞ without an end), a monitor mark when the display is kept awake too; hidden while off (`show = \"always\"` keeps a muted coffee). The popover: the run on a card with the time left and a bar, the presets as tiles on the digits, the display switch, Allow sleep on Enter; `u` opens a field for a time or a duration.",
          "refresh": {
            "every": 60,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 1 min, on wake"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "run",
          "url": "pal://system/run?id=\u003cid\u003e",
          "cli": "pal call system/run id=\u003cid\u003e",
          "description": "Run a system command",
          "confirm": true,
          "params": [
            {
              "name": "id",
              "description": "sleep, lock, logout, restart, shutdown, empty-trash, dark-mode, volume-up, volume-down, volume-mute, brightness-up, brightness-down, dnd, eject-all, show-desktop, keep-awake (the toggle: the default duration, or off), quit-all, unhide-all, dismiss-notifications, quick-look-selection (macOS)",
              "required": true
            }
          ]
        },
        {
          "route": "awake",
          "url": "pal://system/awake",
          "cli": "pal call system/awake",
          "description": "Keep the machine awake, or let it sleep",
          "params": [
            {
              "name": "for",
              "description": "How long: 45m, 2h, 1h30m, or a clock time like 14:30, or forever; blank with nothing else toggles (the default duration, or off while on)"
            },
            {
              "name": "until",
              "description": "The same as for; a clock time reads best here (tomorrow's when today's has passed)"
            },
            {
              "name": "display",
              "description": "Keep the display awake too (the setting otherwise)",
              "type": "boolean"
            },
            {
              "name": "app",
              "description": "An app with a window open: the run ends when it quits (caffeinate -w)"
            },
            {
              "name": "off",
              "description": "Allow sleep now",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "tela",
      "kind": "registry",
      "title": "tela",
      "description": "Your tela wiki in the panel: search as you type, ask questions answered from your pages with their sources, and open recent pages, spaces, decks and sheets. Create a page from selected text and keep up with mentions and replies.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰗚",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/tela@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/tela",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "tela",
        "title": "tela",
        "description": "Your tela wiki in the panel: search as you type, ask questions answered from your pages with their sources, and open recent pages, spaces, decks and sheets. Create a page from selected text and keep up with mentions and replies.",
        "keywords": [
          "wiki"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰗚",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "text",
            "id": "base_url",
            "label": "Address",
            "description": "The tela instance: https://telawiki.com, or your own.",
            "placeholder": "https://telawiki.com",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "token",
            "required": true,
            "label": "Token",
            "description": "A personal access token from Settings, API Keys on tela (tela_pat_...). Read scope lists and searches; write scope creates pages and comments.",
            "placeholder": "tela_pat_...",
            "default": ""
          },
          {
            "kind": "text",
            "id": "default_space",
            "label": "Default space",
            "description": "The space New tela page offers first: its name, slug or id. Empty picks the first space.",
            "placeholder": "Notes",
            "default": ""
          },
          {
            "kind": "boolean",
            "id": "research",
            "label": "Research",
            "text": "Show Ask tela (semantic research)",
            "description": "Needs an embedder configured on the instance; Search works without one.",
            "default": true
          }
        ],
        "palettes": {
          "search": {
            "title": "Search tela",
            "description": "Full-text over every page you can see, ranked, with the matching passage; sections by space.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the page in tela"
              },
              {
                "keys": "cmd+enter",
                "title": "Read the page in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+o",
                "title": "The page's outline"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the page"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Comment on the page"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the markdown (from the page read in pal)"
              }
            ]
          },
          "research": {
            "title": "Ask tela",
            "description": "A question answered by meaning: the pages that matter assembled with their sources, disagreements flagged, low confidence said.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Ask; on a source, open it in tela"
              },
              {
                "keys": "cmd+enter",
                "title": "Ask in the browser; on a source, read it in pal"
              },
              {
                "keys": "down / j, up / k, 1-9",
                "title": "Move between sources"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the source's link"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the grounding"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the question in tela Ask"
              },
              {
                "keys": "+",
                "title": "More sources"
              },
              {
                "keys": "n",
                "title": "New question"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Forget a recent question"
              }
            ]
          },
          "pages": {
            "title": "Pages",
            "description": "Favourites, then what changed lately across spaces; New tela page, Search tela, Ask tela (the question typed in the bar) and Quick Notes at the top. From Spaces, one space's pages.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the page in tela"
              },
              {
                "keys": "cmd+enter",
                "title": "Read the page in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+o",
                "title": "The page's outline"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the page"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Comment on the page"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the markdown (from the page read in pal)"
              }
            ]
          },
          "spaces": {
            "title": "Spaces",
            "description": "Every space the token sees, with its page count; Enter lists its pages.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "keys": [
              {
                "keys": "enter",
                "title": "The space's pages"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the space in tela"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+n",
                "title": "New page in the space"
              }
            ]
          },
          "new-page": {
            "title": "New Page",
            "description": "A page in a space of your choice: title, space, body prefilled from your selection or the clipboard.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "keys": [
              {
                "keys": "enter",
                "title": "The form"
              }
            ]
          },
          "decks": {
            "title": "Decks",
            "description": "Slide decks across spaces, newest first; the pane shows the first slide.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the deck in tela"
              },
              {
                "keys": "cmd+enter",
                "title": "Read the deck's markdown in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+o",
                "title": "The deck's outline"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the deck"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Comment on the deck"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the markdown (from the page read in pal)"
              }
            ]
          },
          "sheets": {
            "title": "Sheets",
            "description": "Spreadsheet pages across spaces, newest first.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the sheet in tela"
              },
              {
                "keys": "cmd+enter",
                "title": "Read the sheet's markdown in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+o",
                "title": "The sheet's outline"
              },
              {
                "keys": "cmd+b",
                "title": "What links to the sheet"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Comment on the sheet"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the markdown (from the page read in pal)"
              }
            ]
          },
          "comments": {
            "title": "Comments",
            "description": "Mentions of you and replies to your comments, unread first; opening one marks it read.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keys": [
              {
                "keys": "enter",
                "title": "Mark read and open the page"
              },
              {
                "keys": "cmd+enter",
                "title": "Read the page in pal"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Mark as read"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+a",
                "title": "Mark all as read"
              }
            ]
          },
          "backlinks": {
            "title": "Backlinks",
            "description": "What links to the page you opened last, or to the page a row's cmd+b came from.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the linking page in tela"
              },
              {
                "keys": "cmd+enter",
                "title": "Read it in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Its outline"
              },
              {
                "keys": "cmd+b",
                "title": "Its own backlinks"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Comment on it"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the markdown (from the page read in pal)"
              }
            ]
          }
        },
        "bar": {
          "inbox": {
            "title": "Inbox",
            "description": "Unread mentions and replies as a badge, hidden at zero; the popover lists every one as a row (the kind's glyph, what happened, the comment's snippet, the time) with a cursor the arrows move and a click sets.",
            "refresh": {
              "every": 300,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "unread": {
                "title": "Mentions and replies",
                "item": {
                  "icon": "󰗚",
                  "badge": 3,
                  "tooltip": "2 mentions, 1 reply"
                }
              },
              "one": {
                "title": "One reply",
                "item": {
                  "icon": "󰗚",
                  "badge": 1,
                  "tooltip": "1 reply"
                }
              },
              "clear": {
                "title": "Nothing unread",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰗚",
                    "tooltip": "Nothing addressed to you"
                  }
                }
              },
              "out": {
                "title": "Signed out",
                "item": {
                  "hidden": true
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the focused comment in tela"
              },
              {
                "keys": "m",
                "title": "Mark the focused one read"
              },
              {
                "keys": "a",
                "title": "Mark every mention and reply read"
              },
              {
                "keys": "o",
                "title": "Open tela"
              },
              {
                "keys": "p",
                "title": "Open the Comments palette in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the rows; a click on a row focuses it"
              }
            ]
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Search, ask and write in your tela wiki from the panel",
          "category": "productivity",
          "features": [
            "Full-text search as you type, grouped by space, with the matching passage; `cmd+enter` reads the page in the panel",
            "Ask tela: a question answered from your pages, with the cited sources and low confidence flagged",
            "Favourites and recent changes across every space; spaces, decks, sheets and backlinks",
            "A new page from the selection or the clipboard; comment on a page anchored to its text",
            "Mentions and replies to your comments, counted on the bar and hidden at zero"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-search.png",
              "caption": "Search tela: ranked hits with the matching passage, sectioned by space"
            },
            {
              "file": "2-research.png",
              "caption": "Ask tela: the sources of an answer as rows, the cited excerpt under the selected one, the flags above"
            },
            {
              "file": "3-page.png",
              "caption": "A page read in pal: headings, callouts, lists, code and tables drawn with the tokens"
            },
            {
              "file": "4-spaces.png",
              "caption": "Spaces with page counts; Enter lists a space's pages"
            },
            {
              "file": "5-new-page.png",
              "caption": "New tela page: title, space, the body prefilled from the clipboard"
            },
            {
              "file": "6-pages.png",
              "caption": "Pages: favourites, then what changed lately, sectioned by space"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the tela glyph with the count of unread mentions and replies",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the newest mentions and replies, Open in pal, Mark all read",
              "kind": "bar",
              "box": [
                436,
                64,
                840,
                518
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the glyph and the count",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open in tela",
              "description": "The page, space or notification in the browser; a notification is marked read first.",
              "keys": "enter"
            },
            {
              "title": "Read in pal",
              "description": "The page's markdown drawn in the panel.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy link",
              "keys": "cmd+c"
            },
            {
              "title": "Outline",
              "description": "The page's headings.",
              "keys": "cmd+shift+o"
            },
            {
              "title": "Backlinks",
              "description": "What links to the page.",
              "keys": "cmd+b"
            },
            {
              "title": "Comment on page",
              "description": "A form: the comment and the passage it anchors on.",
              "keys": "cmd+shift+m"
            },
            {
              "title": "Copy markdown",
              "description": "From a page read in pal.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Ask",
              "description": "Research the question (on the Pages row, typed in the bar's field); on a source in the answer, open it.",
              "keys": "enter"
            },
            {
              "title": "Ask in the browser",
              "description": "tela's Ask page with the question (on the Pages row, typed in the bar's field).",
              "keys": "cmd+enter"
            },
            {
              "title": "Read source in pal",
              "keys": "cmd+enter"
            },
            {
              "title": "Next source / Previous source",
              "keys": "down / up"
            },
            {
              "title": "Copy source link",
              "keys": "cmd+c"
            },
            {
              "title": "Copy the grounding",
              "description": "The numbered excerpts research assembled.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Open in tela Ask",
              "keys": "cmd+shift+o"
            },
            {
              "title": "More sources",
              "description": "When the answer was truncated.",
              "keys": "+"
            },
            {
              "title": "New question",
              "keys": "n"
            },
            {
              "title": "Forget question",
              "keys": "cmd+shift+d"
            },
            {
              "title": "Open pages",
              "description": "A space's pages.",
              "keys": "enter"
            },
            {
              "title": "New page here",
              "description": "The form with the space chosen.",
              "keys": "cmd+n"
            },
            {
              "title": "New page",
              "description": "A form: title, space, body."
            },
            {
              "title": "Search",
              "description": "Search tela from the root row."
            },
            {
              "title": "Open Quick Notes",
              "description": "Your scratchpad page on tela."
            },
            {
              "title": "Mark as read",
              "keys": "cmd+shift+r"
            },
            {
              "title": "Mark all as read",
              "description": "Asks first.",
              "keys": "cmd+shift+a"
            },
            {
              "title": "Read page in pal",
              "description": "From a mention or reply.",
              "keys": "cmd+enter"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/tela",
      "tagline": "Search, ask and write in your tela wiki from the panel",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/tela/screenshots/1-search-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/1-search.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/2-research-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/2-research.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/3-page-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/3-page.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/4-spaces-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/4-spaces.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/5-new-page-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/5-new-page.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/6-pages-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/6-pages.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/tela/screenshots/1-search.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/2-research.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/3-page.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/4-spaces.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/5-new-page.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/6-pages.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/tela/screenshots/1-search-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/2-research-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/3-page-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/4-spaces-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/5-new-page-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/6-pages-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/tela/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "inbox",
          "title": "Inbox",
          "description": "Unread mentions and replies as a badge, hidden at zero; the popover lists every one as a row (the kind's glyph, what happened, the comment's snippet, the time) with a cursor the arrows move and a click sets.",
          "refresh": {
            "every": 300,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "theater",
      "kind": "registry",
      "title": "Theater",
      "description": "Your self-hosted media stack in one place: Jellyfin, Jellyseerr, Radarr, Sonarr, Lidarr, Prowlarr, Bazarr, SABnzbd, qBittorrent, Navidrome, Audiobookshelf, Kavita and more. Fill in the services you run and only those appear.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰿎",
          "bg": "red"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/theater@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/theater",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "theater",
        "title": "Theater",
        "description": "Your self-hosted media stack in one place: Jellyfin, Jellyseerr, Radarr, Sonarr, Lidarr, Prowlarr, Bazarr, SABnzbd, qBittorrent, Navidrome, Audiobookshelf, Kavita and more. Fill in the services you run and only those appear.",
        "keywords": [
          "media",
          "plex",
          "arr"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰿎",
            "bg": "red"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "jellyfin_url",
            "label": "Jellyfin URL",
            "placeholder": "http://marko:8096",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "jellyfin_key",
            "label": "Jellyfin API key",
            "description": "Dashboard › API Keys on the server.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "jellyfin_user",
            "label": "Jellyfin user",
            "description": "Whose Continue Watching and watched state; the first user when empty.",
            "placeholder": "cagdas",
            "default": ""
          },
          {
            "kind": "text",
            "id": "seerr_url",
            "label": "Jellyseerr URL",
            "placeholder": "http://marko:5055",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "seerr_key",
            "label": "Jellyseerr API key",
            "description": "Settings › General on Jellyseerr (Overseerr works the same).",
            "default": ""
          },
          {
            "kind": "text",
            "id": "radarr_url",
            "label": "Radarr URL",
            "placeholder": "http://marko:7878",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "radarr_key",
            "label": "Radarr API key",
            "description": "Settings › General › Security.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "sonarr_url",
            "label": "Sonarr URL",
            "placeholder": "http://marko:8989",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "sonarr_key",
            "label": "Sonarr API key",
            "default": ""
          },
          {
            "kind": "text",
            "id": "lidarr_url",
            "label": "Lidarr URL",
            "placeholder": "http://marko:8686",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "lidarr_key",
            "label": "Lidarr API key",
            "default": ""
          },
          {
            "kind": "text",
            "id": "prowlarr_url",
            "label": "Prowlarr URL",
            "placeholder": "http://marko:9696",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "prowlarr_key",
            "label": "Prowlarr API key",
            "default": ""
          },
          {
            "kind": "text",
            "id": "hydra_url",
            "label": "NZBHydra2 URL",
            "placeholder": "http://marko:5076",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "hydra_key",
            "label": "NZBHydra2 API key",
            "description": "Config › Main › API key.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "bazarr_url",
            "label": "Bazarr URL",
            "placeholder": "http://marko:6767",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "bazarr_key",
            "label": "Bazarr API key",
            "description": "Settings › General › Security.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "sab_url",
            "label": "SABnzbd URL",
            "placeholder": "http://marko:8080",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "sab_key",
            "label": "SABnzbd API key",
            "description": "Config › General › API key (the NZB key is not enough for the queue).",
            "default": ""
          },
          {
            "kind": "text",
            "id": "qbit_url",
            "label": "qBittorrent URL",
            "placeholder": "http://marko:8081",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "qbit_key",
            "label": "qBittorrent API key",
            "description": "qBittorrent 5.2+: a bearer key (POST /api/v2/app/rotateAPIKey from a logged-in session). Leave empty to sign in with the WebUI user and password instead.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "qbit_user",
            "label": "qBittorrent user",
            "placeholder": "admin",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "qbit_password",
            "label": "qBittorrent password",
            "default": ""
          },
          {
            "kind": "text",
            "id": "navidrome_url",
            "label": "Navidrome URL",
            "placeholder": "http://marko:4533",
            "default": ""
          },
          {
            "kind": "text",
            "id": "navidrome_user",
            "label": "Navidrome user",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "navidrome_password",
            "label": "Navidrome password",
            "description": "Sent as a Subsonic salted token, never in clear.",
            "default": ""
          },
          {
            "kind": "text",
            "id": "abs_url",
            "label": "Audiobookshelf URL",
            "placeholder": "http://marko:13378",
            "default": ""
          },
          {
            "kind": "text",
            "id": "abs_user",
            "label": "Audiobookshelf user",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "abs_password",
            "label": "Audiobookshelf password",
            "default": ""
          },
          {
            "kind": "text",
            "id": "kavita_url",
            "label": "Kavita URL",
            "placeholder": "http://marko:5001",
            "default": ""
          },
          {
            "kind": "text",
            "id": "kavita_user",
            "label": "Kavita user",
            "default": ""
          },
          {
            "kind": "secret",
            "id": "kavita_password",
            "label": "Kavita password",
            "default": ""
          },
          {
            "kind": "text",
            "id": "shelfmark_url",
            "label": "Shelfmark URL",
            "description": "The book request door (no auth).",
            "placeholder": "http://marko:8084",
            "default": ""
          },
          {
            "kind": "text",
            "id": "filebrowser_url",
            "label": "Filebrowser URL",
            "description": "Opened from the Theater palette.",
            "placeholder": "http://marko:8082",
            "default": ""
          },
          {
            "kind": "text",
            "id": "homepage_url",
            "label": "Homepage URL",
            "description": "The dashboard; opened from the Theater palette.",
            "placeholder": "http://marko:3001",
            "default": ""
          }
        ],
        "palettes": {
          "theater": {
            "title": "Theater",
            "description": "Every configured service as a row with live health (up or down, version, one key number); Enter opens its web UI, cmd+Enter its palette in pal. A service you have not set up is one Set up row.",
            "kind": "live",
            "lazy": true,
            "ttl": 30,
            "keywords": [
              "stack",
              "media",
              "services"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the service's web UI"
              },
              {
                "keys": "cmd+enter",
                "title": "The service in pal"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the URL"
              },
              {
                "keys": "cmd+r",
                "title": "Check again"
              }
            ]
          },
          "jellyfin": {
            "title": "Jellyfin",
            "description": "Continue Watching with the position, then the latest additions, posters on the rows; the pane has the overview, year, rating, runtime and watched state.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "jf",
              "continue",
              "watch"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Jellyfin"
              },
              {
                "keys": "cmd+enter",
                "title": "Play on a device (a picker of the signed-in sessions)"
              },
              {
                "keys": "cmd+shift+p",
                "title": "Mark played or unplayed"
              },
              {
                "keys": "cmd+f",
                "title": "Add to or remove from favourites"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "jellyfin-search": {
            "title": "Search Jellyfin",
            "description": "Movies, series, episodes, albums and songs by title, 300 ms after the last key; the same actions as the Jellyfin rows.",
            "kind": "input",
            "keywords": [
              "jf"
            ],
            "fallback": "Search Jellyfin for “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Jellyfin"
              },
              {
                "keys": "cmd+enter",
                "title": "Play on a device"
              },
              {
                "keys": "cmd+shift+p",
                "title": "Mark played or unplayed"
              },
              {
                "keys": "cmd+f",
                "title": "Favourite"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "jellyfin-playing": {
            "title": "Now Playing on Jellyfin",
            "description": "Active sessions: who watches what on which device, with the position; Enter opens the item, cmd+Enter pauses or resumes that session.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 30,
            "keywords": [
              "sessions",
              "watching",
              "jf"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the item in Jellyfin"
              },
              {
                "keys": "cmd+enter",
                "title": "Pause or resume the session"
              },
              {
                "keys": "cmd+shift+s",
                "title": "Stop playback"
              }
            ]
          },
          "jellyfin-play": {
            "title": "Play on",
            "description": "The picker Play on a device opens: every Jellyfin session that takes remote control; Enter plays the item there.",
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Play the item on that session"
              }
            ]
          },
          "seerr-requests": {
            "title": "Requests",
            "description": "Jellyseerr requests, pending first, with the poster, who asked and the status; Approve and Decline on a pending one. The filter narrows to pending, approved, available or all.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "jellyseerr",
              "overseerr",
              "seerr",
              "pending"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Jellyseerr"
              },
              {
                "keys": "cmd+enter",
                "title": "Approve (a pending request)"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Decline (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "seerr-request": {
            "title": "Request a title",
            "description": "Search TMDB through Jellyseerr; Enter requests the movie or series (asks first), cmd+Enter in 4K when the server allows it. A title already available or requested is tagged.",
            "kind": "input",
            "keywords": [
              "jellyseerr",
              "overseerr",
              "seerr",
              "tmdb"
            ],
            "fallback": "Request “{query}” on Jellyseerr",
            "keys": [
              {
                "keys": "enter",
                "title": "Request (asks first)"
              },
              {
                "keys": "cmd+enter",
                "title": "Request in 4K, when enabled"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Jellyseerr"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the TMDB link"
              }
            ]
          },
          "radarr": {
            "title": "Radarr",
            "description": "The queue with progress and status, the next seven days, health warnings, and the commands: add a movie, wanted, history, sync the watchlist now, open Radarr.",
            "kind": "live",
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "movies",
              "queue"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Radarr"
              },
              {
                "keys": "cmd+backspace",
                "title": "Remove from the queue (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the title"
              }
            ]
          },
          "radarr-add": {
            "title": "Add a movie",
            "description": "Look a movie up on Radarr; Enter adds it with the default quality profile and root folder and searches (asks first). One already in the library is tagged.",
            "kind": "input",
            "keywords": [
              "radarr",
              "movie"
            ],
            "fallback": "Add “{query}” to Radarr",
            "keys": [
              {
                "keys": "enter",
                "title": "Add and search (asks first)"
              },
              {
                "keys": "cmd+enter",
                "title": "Add without searching"
              },
              {
                "keys": "cmd+o",
                "title": "Open on TMDB"
              }
            ]
          },
          "radarr-wanted": {
            "title": "Wanted movies",
            "description": "Monitored movies without a file, newest release first; Enter searches for one, cmd+Enter opens it.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "radarr",
              "missing"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Search for the movie now"
              },
              {
                "keys": "cmd+enter",
                "title": "Open in Radarr"
              }
            ]
          },
          "radarr-history": {
            "title": "Radarr history",
            "description": "What Radarr grabbed, imported or failed on lately.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "radarr"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the movie in Radarr"
              }
            ]
          },
          "sonarr": {
            "title": "Sonarr",
            "description": "The queue with progress and status, the episodes airing in the next seven days, health warnings, and the commands: add a series, wanted, history, sync the watchlist now, open Sonarr.",
            "kind": "live",
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "tv",
              "series",
              "queue"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Sonarr"
              },
              {
                "keys": "cmd+backspace",
                "title": "Remove from the queue (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the title"
              }
            ]
          },
          "sonarr-add": {
            "title": "Add a series",
            "description": "Look a series up on Sonarr; Enter adds it with the default quality profile and root folder, every season monitored, and searches (asks first).",
            "kind": "input",
            "keywords": [
              "sonarr",
              "tv",
              "show"
            ],
            "fallback": "Add “{query}” to Sonarr",
            "keys": [
              {
                "keys": "enter",
                "title": "Add and search (asks first)"
              },
              {
                "keys": "cmd+enter",
                "title": "Add without searching"
              },
              {
                "keys": "cmd+o",
                "title": "Open on TVDB"
              }
            ]
          },
          "sonarr-wanted": {
            "title": "Wanted episodes",
            "description": "Monitored episodes that aired without a file, newest first; Enter searches for one.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "sonarr",
              "missing"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Search for the episode now"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the series in Sonarr"
              }
            ]
          },
          "sonarr-history": {
            "title": "Sonarr history",
            "description": "What Sonarr grabbed, imported or failed on lately.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "sonarr"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the series in Sonarr"
              }
            ]
          },
          "lidarr": {
            "title": "Lidarr",
            "description": "The queue with progress and status, albums out in the next seven days, health warnings, and the commands: add an artist, wanted, history, open Lidarr.",
            "kind": "live",
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "music",
              "queue"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Lidarr"
              },
              {
                "keys": "cmd+backspace",
                "title": "Remove from the queue (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the title"
              }
            ]
          },
          "lidarr-add": {
            "title": "Add an artist",
            "description": "Look an artist up on Lidarr; Enter adds them with the default profiles and root folder and searches for missing albums (asks first).",
            "kind": "input",
            "keywords": [
              "lidarr",
              "music",
              "band"
            ],
            "fallback": "Add “{query}” to Lidarr",
            "keys": [
              {
                "keys": "enter",
                "title": "Add and search (asks first)"
              },
              {
                "keys": "cmd+enter",
                "title": "Add without searching"
              },
              {
                "keys": "cmd+o",
                "title": "Open on MusicBrainz"
              }
            ]
          },
          "lidarr-wanted": {
            "title": "Wanted albums",
            "description": "Monitored albums without files, newest first; Enter searches for one.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "lidarr",
              "missing"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Search for the album now"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the artist in Lidarr"
              }
            ]
          },
          "lidarr-history": {
            "title": "Lidarr history",
            "description": "What Lidarr grabbed, imported or failed on lately.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "lidarr"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the artist in Lidarr"
              }
            ]
          },
          "downloads": {
            "title": "Downloads",
            "description": "SABnzbd and qBittorrent as one queue: each item with progress, speed, time left and category; pause, resume and delete per item; Pause all, Resume all and a speed limit on top.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 20,
            "keywords": [
              "sab",
              "sabnzbd",
              "qbit",
              "qbittorrent",
              "torrents",
              "usenet",
              "queue"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the download client"
              },
              {
                "keys": "cmd+enter",
                "title": "Pause or resume the item"
              },
              {
                "keys": "cmd+backspace",
                "title": "Delete the item (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the name"
              }
            ]
          },
          "downloads-history": {
            "title": "Download history",
            "description": "What SABnzbd and qBittorrent finished lately, a failed one with its reason.",
            "kind": "list",
            "lazy": true,
            "ttl": 120,
            "keywords": [
              "sab",
              "sabnzbd",
              "qbit",
              "finished",
              "failed"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the download client"
              },
              {
                "keys": "cmd+backspace",
                "title": "Remove from the history (asks first)"
              }
            ]
          },
          "prowlarr": {
            "title": "Indexers",
            "description": "Every Prowlarr indexer with protocol, priority and health (a disabled or failing one says why), Prowlarr's own health warnings, and NZBHydra2's indexers when configured.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "prowlarr",
              "hydra",
              "nzbhydra",
              "trackers"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open the indexer in Prowlarr"
              },
              {
                "keys": "cmd+enter",
                "title": "Test the indexer"
              }
            ]
          },
          "prowlarr-search": {
            "title": "Search indexers",
            "description": "A release search across every Prowlarr indexer: title, size, age, seeders or grabs, the indexer as a tag; Enter grabs it through Prowlarr into the download client (asks first).",
            "kind": "input",
            "keywords": [
              "prowlarr",
              "nzb",
              "torrent",
              "release"
            ],
            "fallback": "Search the indexers for “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "Grab through Prowlarr (asks first)"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the release page"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the download link"
              }
            ]
          },
          "hydra-search": {
            "title": "Search NZBHydra2",
            "description": "A usenet search through NZBHydra2: title, size, age, grabs, the indexer as a tag; Enter sends the NZB to SABnzbd when it is configured, else opens Hydra.",
            "kind": "input",
            "keywords": [
              "hydra",
              "nzbhydra",
              "usenet",
              "nzb"
            ],
            "fallback": "Search NZBHydra2 for “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "Send to SABnzbd (asks first), or open in Hydra"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the release's page"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the NZB link"
              }
            ]
          },
          "navidrome": {
            "title": "Navidrome",
            "description": "What is playing now, then the albums added lately with their covers; Enter opens in Navidrome, cmd+S stars.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "music",
              "subsonic",
              "albums"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Navidrome"
              },
              {
                "keys": "cmd+s",
                "title": "Star or unstar"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "navidrome-search": {
            "title": "Search Navidrome",
            "description": "Artists, albums and songs with cover art, 300 ms after the last key.",
            "kind": "input",
            "keywords": [
              "music",
              "subsonic",
              "song",
              "album",
              "artist"
            ],
            "fallback": "Search Navidrome for “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Navidrome"
              },
              {
                "keys": "cmd+s",
                "title": "Star or unstar"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "abs": {
            "title": "Audiobookshelf",
            "description": "Continue listening with the progress, then what was added lately across your libraries; Enter opens in Audiobookshelf.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "audiobooks",
              "podcasts",
              "listen"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Audiobookshelf"
              },
              {
                "keys": "cmd+shift+p",
                "title": "Mark finished"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "abs-search": {
            "title": "Search Audiobookshelf",
            "description": "Books, podcasts and authors across every library.",
            "kind": "input",
            "keywords": [
              "audiobooks",
              "podcasts"
            ],
            "fallback": "Search Audiobookshelf for “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Audiobookshelf"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "kavita": {
            "title": "Kavita",
            "description": "Continue reading with the pages read, then the series added lately; Enter opens the web reader.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "ttl": 60,
            "keywords": [
              "ebooks",
              "read",
              "books",
              "comics"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Kavita"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "kavita-search": {
            "title": "Search Kavita",
            "description": "Series, collections and files across your libraries.",
            "kind": "input",
            "keywords": [
              "ebooks",
              "books"
            ],
            "fallback": "Search Kavita for “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Kavita"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the link"
              }
            ]
          },
          "shelfmark": {
            "title": "Request a book",
            "description": "Search Shelfmark's book provider; Enter lists the releases found for the book, and Enter on one downloads it into the ebook library (asks first). With nothing typed, what Shelfmark is downloading now.",
            "kind": "input",
            "keywords": [
              "shelfmark",
              "getbooks",
              "ebook",
              "book"
            ],
            "fallback": "Request the book “{query}”",
            "keys": [
              {
                "keys": "enter",
                "title": "The releases for the book"
              },
              {
                "keys": "cmd+enter",
                "title": "Open Shelfmark"
              }
            ]
          },
          "shelfmark-releases": {
            "title": "Releases",
            "description": "The releases Shelfmark found for one book (opened from Request a book): format, size, source, seeders; Enter downloads (asks first).",
            "kind": "list",
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Download the release (asks first)"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the release title"
              }
            ]
          },
          "bazarr": {
            "title": "Subtitles",
            "description": "Bazarr: how many movies and episodes still want subtitles, each provider's health, and the wanted items with the missing languages; Search missing subtitles runs Bazarr's task.",
            "kind": "list",
            "lazy": true,
            "ttl": 300,
            "keywords": [
              "bazarr",
              "subs",
              "subtitles"
            ],
            "keys": [
              {
                "keys": "enter",
                "title": "Open in Bazarr"
              },
              {
                "keys": "cmd+enter",
                "title": "Search subtitles for the item"
              }
            ]
          }
        },
        "bar": {
          "downloads": {
            "title": "Downloads",
            "description": "SABnzbd and qBittorrent together: the download speed and how many items are active; hidden while both are idle. The popover lists the queue with progress bars, space pauses or resumes everything.",
            "refresh": {
              "every": 15,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "rules": [
              {
                "id": "paused",
                "when": "theater.paused",
                "description": "Everything is paused.",
                "color": "amber"
              }
            ],
            "mocks": {
              "busy": {
                "title": "Downloading",
                "item": {
                  "icon": "󰇚",
                  "title": "4.2 MB/s · 3",
                  "tooltip": "3 downloading, 4.2 MB/s"
                }
              },
              "paused": {
                "title": "Paused",
                "item": {
                  "icon": "󰏤",
                  "title": "paused · 2",
                  "color": "amber",
                  "tooltip": "2 in the queue, paused"
                }
              },
              "idle": {
                "title": "Idle, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰇚",
                    "tooltip": "Nothing downloading"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the client of the focused item"
              },
              {
                "keys": "space",
                "title": "Pause or resume everything"
              },
              {
                "keys": "backspace",
                "title": "Delete the focused item (asks first)"
              },
              {
                "keys": "p",
                "title": "Open Downloads in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the items"
              }
            ]
          },
          "playing": {
            "title": "Now Playing",
            "description": "Who is watching what on Jellyfin: the count on the strip, the sessions with progress in the popover; hidden while nothing plays.",
            "refresh": {
              "every": 30,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "one": {
                "title": "One stream",
                "item": {
                  "icon": "󰐊",
                  "title": "cagdas",
                  "tooltip": "cagdas · Barry S1E4 on the living room TV"
                }
              },
              "two": {
                "title": "Two streams",
                "item": {
                  "icon": "󰐊",
                  "title": "2",
                  "tooltip": "cagdas and a guest are watching"
                }
              },
              "idle": {
                "title": "Nothing playing, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰐊",
                    "tooltip": "Nothing playing on Jellyfin"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the item in Jellyfin"
              },
              {
                "keys": "space",
                "title": "Pause or resume the focused session"
              },
              {
                "keys": "p",
                "title": "Open Now Playing in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the sessions"
              }
            ]
          },
          "requests": {
            "title": "Requests",
            "description": "Pending Jellyseerr requests as the badge, hidden at zero; the popover lists them with the poster; a approves and d declines the focused one.",
            "refresh": {
              "every": 300,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "pending": {
                "title": "Two pending",
                "item": {
                  "icon": "󰋻",
                  "badge": 2,
                  "tooltip": "2 pending requests"
                }
              },
              "none": {
                "title": "Nothing pending, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰋻",
                    "tooltip": "No pending requests"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the request in Jellyseerr"
              },
              {
                "keys": "a",
                "title": "Approve the focused request"
              },
              {
                "keys": "d",
                "title": "Decline the focused request (asks first)"
              },
              {
                "keys": "p",
                "title": "Open Requests in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the requests"
              }
            ]
          },
          "queue": {
            "title": "Arr queue",
            "description": "What Radarr, Sonarr and Lidarr are fetching or importing: the count on the strip, amber when an item is stuck (an import that needs a hand, a failed download); hidden while every queue is empty.",
            "refresh": {
              "every": 60,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "rules": [
              {
                "id": "stuck",
                "when": "theater.stuck \u003e 0",
                "description": "An item needs attention.",
                "color": "amber"
              }
            ],
            "mocks": {
              "busy": {
                "title": "Fetching",
                "item": {
                  "icon": "󰦗",
                  "title": "3",
                  "tooltip": "3 in the arr queues"
                }
              },
              "stuck": {
                "title": "One stuck",
                "item": {
                  "icon": "󰦗",
                  "title": "3",
                  "badge": 1,
                  "color": "amber",
                  "tooltip": "3 in the queues, 1 needs attention"
                }
              },
              "idle": {
                "title": "Empty, hidden",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰦗",
                    "tooltip": "The arr queues are empty"
                  }
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the item's app"
              },
              {
                "keys": "backspace",
                "title": "Remove the focused item from its queue (asks first)"
              },
              {
                "keys": "p",
                "title": "Open the app's palette in pal"
              },
              {
                "keys": "up, down",
                "title": "Move between the items"
              }
            ]
          }
        },
        "states": {
          "downloading": {
            "description": "Items downloading across SABnzbd and qBittorrent",
            "kind": "number"
          },
          "speed": {
            "description": "Combined download speed, bytes per second",
            "kind": "number"
          },
          "paused": {
            "description": "Every download client is paused",
            "kind": "boolean"
          },
          "watching": {
            "description": "Jellyfin sessions playing something",
            "kind": "number"
          },
          "pending": {
            "description": "Jellyseerr requests waiting for approval",
            "kind": "number"
          },
          "queued": {
            "description": "Items across the Radarr, Sonarr and Lidarr queues",
            "kind": "number"
          },
          "stuck": {
            "description": "Queue items with a warning or an error",
            "kind": "number"
          }
        },
        "links": {
          "search": {
            "description": "Open Search Jellyfin with a query typed",
            "params": {
              "q": {
                "description": "What to search for"
              }
            }
          },
          "request": {
            "description": "Open Request a title with a query typed",
            "params": {
              "q": {
                "description": "The title to look up on Jellyseerr"
              }
            }
          },
          "downloads": {
            "description": "Open the Downloads palette"
          },
          "pause-all": {
            "description": "Pause SABnzbd and qBittorrent"
          },
          "resume-all": {
            "description": "Resume SABnzbd and qBittorrent"
          },
          "sync-watchlist": {
            "description": "Run an import list sync now (Radarr, Sonarr)",
            "params": {
              "app": {
                "description": "radarr or sonarr; both when omitted"
              }
            }
          },
          "open": {
            "description": "Open a service's web UI",
            "params": {
              "service": {
                "description": "jellyfin, seerr, radarr, sonarr, lidarr, prowlarr, hydra, bazarr, sab, qbit, navidrome, abs, kavita, shelfmark, filebrowser, homepage",
                "required": true
              }
            }
          }
        },
        "store": {
          "tagline": "Jellyfin, the arr apps, downloads, music and books in one place",
          "category": "productivity",
          "features": [
            "Every service you set up as a row with its health; `enter` opens its web page, `cmd+enter` its list",
            "Jellyfin: Continue Watching and Latest with posters, search, Now Playing, play on a device",
            "Jellyseerr requests to approve or decline, and new requests from a title search",
            "Radarr, Sonarr and Lidarr: queue, calendar, wanted and history; add a title with the default profile",
            "SABnzbd and qBittorrent as one downloads queue: pause, resume, delete, limit the speed",
            "Bar items for download speed, who is watching, pending requests and the arr queue, hidden when idle"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-theater.png",
              "caption": "Every service of the home media stack on one list: its version, what it is doing, and what needs a hand"
            },
            {
              "file": "2-jellyfin.png",
              "caption": "Jellyfin: what you are halfway through and what just arrived, how far in and the rating; cmd+Enter plays it on the TV"
            },
            {
              "file": "3-requests.png",
              "caption": "Requests: the pending ones first with who asked, 4K and where each one stands; approve or decline from the row"
            },
            {
              "file": "4-sonarr.png",
              "caption": "Sonarr: its commands, its health, an import stuck in the queue with the reason, and what airs this week"
            },
            {
              "file": "5-downloads.png",
              "caption": "SABnzbd and qBittorrent in one list: speed, time left and size; pause everything or set a limit"
            },
            {
              "file": "6-indexers.png",
              "caption": "One search across every Prowlarr indexer, grouped by indexer with size, age and grabs; Enter sends it to the downloader"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the combined download speed and how many items are active",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-paused.png",
              "caption": "Everything paused: the item turns amber and says how many wait in the queue",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the queue: every item with its progress bar, space pauses everything",
              "kind": "bar",
              "box": [
                374,
                64,
                840,
                864
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the speed and the count",
              "kind": "bar"
            }
          ]
        },
        "controls": [
          "player"
        ]
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/theater",
      "tagline": "Jellyfin, the arr apps, downloads, music and books in one place",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/theater/screenshots/1-theater-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/1-theater.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/2-jellyfin-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/2-jellyfin.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/3-requests-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/3-requests.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/4-sonarr-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/4-sonarr.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/5-downloads-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/5-downloads.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/6-indexers-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/6-indexers.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar-paused-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar-paused.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/theater/screenshots/1-theater.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/2-jellyfin.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/3-requests.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/4-sonarr.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/5-downloads.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/6-indexers.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar-paused.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/theater/screenshots/1-theater-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/2-jellyfin-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/3-requests-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/4-sonarr-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/5-downloads-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/6-indexers-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar-paused-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/theater/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "downloads",
          "title": "Downloads",
          "description": "SABnzbd and qBittorrent together: the download speed and how many items are active; hidden while both are idle. The popover lists the queue with progress bars, space pauses or resumes everything.",
          "refresh": {
            "every": 15,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 15s, when the panel shows, on wake, when the network is back"
        },
        {
          "id": "playing",
          "title": "Now Playing",
          "description": "Who is watching what on Jellyfin: the count on the strip, the sessions with progress in the popover; hidden while nothing plays.",
          "refresh": {
            "every": 30,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 30s, when the panel shows, on wake, when the network is back"
        },
        {
          "id": "requests",
          "title": "Requests",
          "description": "Pending Jellyseerr requests as the badge, hidden at zero; the popover lists them with the poster; a approves and d declines the focused one.",
          "refresh": {
            "every": 300,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 5 min, when the panel shows, on wake, when the network is back"
        },
        {
          "id": "queue",
          "title": "Arr queue",
          "description": "What Radarr, Sonarr and Lidarr are fetching or importing: the count on the strip, amber when an item is stuck (an import that needs a hand, a failed download); hidden while every queue is empty.",
          "refresh": {
            "every": 60,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 1 min, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "search",
          "url": "pal://theater/search",
          "cli": "pal call theater/search",
          "description": "Open Search Jellyfin with a query typed",
          "params": [
            {
              "name": "q",
              "description": "What to search for"
            }
          ]
        },
        {
          "route": "request",
          "url": "pal://theater/request",
          "cli": "pal call theater/request",
          "description": "Open Request a title with a query typed",
          "params": [
            {
              "name": "q",
              "description": "The title to look up on Jellyseerr"
            }
          ]
        },
        {
          "route": "downloads",
          "url": "pal://theater/downloads",
          "cli": "pal call theater/downloads",
          "description": "Open the Downloads palette",
          "params": []
        },
        {
          "route": "pause-all",
          "url": "pal://theater/pause-all",
          "cli": "pal call theater/pause-all",
          "description": "Pause SABnzbd and qBittorrent",
          "params": []
        },
        {
          "route": "resume-all",
          "url": "pal://theater/resume-all",
          "cli": "pal call theater/resume-all",
          "description": "Resume SABnzbd and qBittorrent",
          "params": []
        },
        {
          "route": "sync-watchlist",
          "url": "pal://theater/sync-watchlist",
          "cli": "pal call theater/sync-watchlist",
          "description": "Run an import list sync now (Radarr, Sonarr)",
          "params": [
            {
              "name": "app",
              "description": "radarr or sonarr; both when omitted"
            }
          ]
        },
        {
          "route": "open",
          "url": "pal://theater/open?service=\u003cservice\u003e",
          "cli": "pal call theater/open service=\u003cservice\u003e",
          "description": "Open a service's web UI",
          "params": [
            {
              "name": "service",
              "description": "jellyfin, seerr, radarr, sonarr, lidarr, prowlarr, hydra, bazarr, sab, qbit, navidrome, abs, kavita, shelfmark, filebrowser, homepage",
              "required": true
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "timer",
      "kind": "bundled",
      "title": "Timer",
      "description": "Named countdown timers and pomodoros: the soonest one counts down on the bar and turns into an alarm when it ends. Built on the `timer` command line tool, so timers started in a terminal show up here too.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰔛",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/timer@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/timer",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "timer",
        "title": "Timer",
        "description": "Named countdown timers and pomodoros: the soonest one counts down on the bar and turns into an alarm when it ends. Built on the `timer` command line tool, so timers started in a terminal show up here too.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰔛",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "settings": [
          {
            "kind": "path",
            "id": "command",
            "label": "timer command",
            "description": "The timer CLI (a name on PATH or a path). It keeps the timers; pal only reads and asks.",
            "pick": "file",
            "default": "timer"
          },
          {
            "kind": "path",
            "id": "dir",
            "label": "State directory",
            "description": "Where the CLI keeps one file per timer (its TIMER_DIR). ~ is expanded.",
            "pick": "folder",
            "default": "~/.local/share/timer"
          },
          {
            "kind": "number",
            "id": "pomodoro_work",
            "label": "Pomodoro work",
            "description": "Minutes of work per round.",
            "min": 1,
            "max": 180,
            "unit": "min",
            "default": 25
          },
          {
            "kind": "number",
            "id": "pomodoro_break",
            "label": "Pomodoro break",
            "description": "Minutes of break after a round.",
            "min": 1,
            "max": 60,
            "unit": "min",
            "default": 5
          },
          {
            "kind": "number",
            "id": "pomodoro_long_break",
            "label": "Pomodoro long break",
            "description": "Minutes of break after the last round of a cycle.",
            "min": 1,
            "max": 120,
            "unit": "min",
            "default": 15
          },
          {
            "kind": "number",
            "id": "pomodoro_rounds",
            "label": "Pomodoro rounds",
            "description": "Work rounds per cycle before the long break.",
            "min": 1,
            "max": 12,
            "unit": "rounds",
            "default": 4
          }
        ],
        "links": {
          "start": {
            "description": "Start a timer",
            "params": {
              "duration": {
                "description": "25m, 90s, 1h30m, 2:30, or minutes as a bare number",
                "required": true
              },
              "name": {
                "description": "Optional; the duration otherwise. A name already taken restarts that timer"
              },
              "ring": {
                "description": "Ring the phone out loud when it lands",
                "type": "boolean"
              }
            }
          }
        },
        "palettes": {
          "timers": {
            "title": "Timers",
            "description": "Every timer with what is left; New timer takes a duration, a name and whether to ring the phone in the bar; Start Pomodoro runs work and break timers in turn.",
            "kind": "live",
            "remember": false,
            "keys": [
              {
                "keys": "enter",
                "title": "Pause, resume or dismiss"
              },
              {
                "keys": "cmd++",
                "title": "Add the minutes typed in the bar (five when blank)"
              },
              {
                "keys": "cmd+s",
                "title": "Skip to the pomodoro's next phase"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Stop the pomodoro"
              },
              {
                "keys": "cmd+d",
                "title": "Stop"
              }
            ]
          }
        },
        "bar": {
          "timer": {
            "title": "Timer",
            "description": "The soonest timer's remaining time with a fill; an alarm once it lands; hidden with none running. The popover: the soonest timer's time left as its headline, a card with a bar for each other one, pause, add five minutes, stop, a field to start one, a pomodoro's phase and round on its card.",
            "mocks": {
              "plain": {
                "title": "A timer running",
                "item": {
                  "icon": "󰥔",
                  "title": "8:12",
                  "progress": 0.18,
                  "color": "blue",
                  "tooltip": "Tea"
                }
              },
              "running": {
                "title": "A pomodoro round running",
                "item": {
                  "icon": "󰥔",
                  "title": "12:34 · 2/4",
                  "progress": 0.58,
                  "color": "blue",
                  "tooltip": "Pomodoro: round 2 of 4, work"
                }
              },
              "ending": {
                "title": "Nearly landed, another timer behind it",
                "item": {
                  "icon": "󰥔",
                  "title": "0:41",
                  "progress": 0.95,
                  "color": "red",
                  "tooltip": "Tea (+1 more)"
                }
              },
              "paused": {
                "title": "Paused timer",
                "item": {
                  "icon": "󰥔",
                  "title": "41:05",
                  "progress": 0.32,
                  "color": "muted",
                  "tooltip": "Tea, paused"
                }
              },
              "landed": {
                "title": "Timer landed",
                "item": {
                  "icon": "󰥔",
                  "title": "Tea",
                  "urgent": true,
                  "progress": 1,
                  "tooltip": "Tea landed 0:03 ago"
                }
              },
              "idle": {
                "title": "No timers",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰥔",
                    "tooltip": "No timers"
                  }
                }
              }
            },
            "refresh": {
              "every": 10,
              "on": [
                "wake"
              ]
            },
            "keys": [
              {
                "keys": "space",
                "title": "Pause, resume or dismiss the timer with the ring"
              },
              {
                "keys": "+",
                "title": "Add five minutes"
              },
              {
                "keys": "backspace",
                "title": "Stop"
              },
              {
                "keys": "up",
                "title": "Move the ring to another timer (or click a card)"
              },
              {
                "keys": "n",
                "title": "Start one: type 25m tea in the field, Enter"
              },
              {
                "keys": "p",
                "title": "Start a pomodoro"
              },
              {
                "keys": "s",
                "title": "Skip to the pomodoro's next phase"
              },
              {
                "keys": "cmd+shift+d",
                "title": "Stop the pomodoro"
              },
              {
                "keys": "o",
                "title": "Open the Timers palette"
              }
            ]
          }
        },
        "license": "MIT",
        "store": {
          "tagline": "Named countdowns and pomodoros, with an alarm on the bar",
          "category": "productivity",
          "features": [
            "One row per timer, most urgent first, with the time left or when it ended",
            "Start one by typing `25m`, `90s` or `1h30m` and a name; optionally ring the phone when it ends",
            "`enter` pauses, resumes or dismisses; `cmd++` adds minutes (five when none are typed); `cmd+d` stops",
            "Pomodoro: 25 minutes of work, 5 of break, 15 after the fourth round; `cmd+s` skips a phase",
            "A bar item with the countdown filling blue to amber to red; its popover pauses, adds time or starts a timer",
            "The same timers as the `timer` CLI, so one started in a terminal is in this list"
          ],
          "permissions": [
            "timer"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-timers.png",
              "caption": "Every timer, the most urgent first: one that just landed, three running with when each lands, one paused, and the pomodoros done today"
            },
            {
              "file": "2-actions.png",
              "caption": "A running timer's actions: pause it, stop it, or add the minutes in the field beside the search (five unless you type more)"
            },
            {
              "file": "3-pomodoro.png",
              "caption": "A pomodoro round is a timer too: its row says the round and the phase, and skips to the break or stops the cycle"
            },
            {
              "file": "4-new.png",
              "caption": "New timer, typed after the search: a duration as you would say it, an optional name, and whether the phone rings when it lands"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: what is left of the soonest timer, with a fill under the glyph that turns amber past two thirds",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-landed.png",
              "caption": "A timer that landed: the item turns into a red alarm with its name",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: a card per timer with the time left and a bar; space pauses, + adds five minutes, backspace stops",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                868
              ]
            },
            {
              "file": "bar-popover-landed.png",
              "caption": "A landed timer sits on top, red and full, until space dismisses it",
              "kind": "bar",
              "box": [
                416,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-new.png",
              "caption": "n opens the field: 25m tea starts one, and the last durations are a click away",
              "kind": "bar",
              "box": [
                420,
                64,
                840,
                786
              ]
            },
            {
              "file": "bar-popover-pomodoro.png",
              "caption": "A pomodoro on the popover: the round and the phase on its card, s skips to the break, the rounds finished today below",
              "kind": "bar",
              "box": [
                382,
                64,
                840,
                712
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the fill as a rule of box-drawing cells before the glyph, the countdown as the label",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Pause / Resume / Dismiss",
              "description": "Pause a running timer, resume a paused one, dismiss a landed one.",
              "keys": "enter"
            },
            {
              "title": "Add minutes",
              "description": "The minutes typed in the bar, five when blank.",
              "keys": "cmd++"
            },
            {
              "title": "Stop",
              "description": "The timer is gone.",
              "keys": "cmd+d"
            },
            {
              "title": "Start",
              "description": "On New timer: the bar takes the duration (required), a name and Silent or Ring the phone, then the CLI starts it.",
              "keys": "enter"
            },
            {
              "title": "Start pomodoro",
              "description": "The Start Pomodoro row: the first work round's timer, the breaks and the next rounds follow on their own.",
              "keys": "enter"
            },
            {
              "title": "Skip to the next phase",
              "description": "On the pomodoro's timer: this phase's timer stopped, the next started.",
              "keys": "cmd+s"
            },
            {
              "title": "Stop pomodoro",
              "description": "The cycle is over; the timer stopped.",
              "keys": "cmd+shift+d"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/timer",
      "tagline": "Named countdowns and pomodoros, with an alarm on the bar",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/timer/screenshots/1-timers-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/1-timers.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/3-pomodoro-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/3-pomodoro.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/4-new-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/4-new.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar-landed-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar-landed.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-landed-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-landed.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-new-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-new.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-pomodoro-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-pomodoro.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/timer/screenshots/1-timers.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/3-pomodoro.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/4-new.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar-landed.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-landed.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-new.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-pomodoro.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/timer/screenshots/1-timers-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/3-pomodoro-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/4-new-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar-landed-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-landed-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-new-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-pomodoro-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/timer/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "timer",
          "title": "Timer",
          "description": "The soonest timer's remaining time with a fill; an alarm once it lands; hidden with none running. The popover: the soonest timer's time left as its headline, a card with a bar for each other one, pause, add five minutes, stop, a field to start one, a pomodoro's phase and round on its card.",
          "refresh": {
            "every": 10,
            "on": [
              "wake"
            ]
          },
          "refresh_words": "every 10s, on wake"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "start",
          "url": "pal://timer/start?duration=\u003cduration\u003e",
          "cli": "pal call timer/start duration=\u003cduration\u003e",
          "description": "Start a timer",
          "params": [
            {
              "name": "duration",
              "description": "25m, 90s, 1h30m, 2:30, or minutes as a bare number",
              "required": true
            },
            {
              "name": "name",
              "description": "Optional; the duration otherwise. A name already taken restarts that timer"
            },
            {
              "name": "ring",
              "description": "Ring the phone out loud when it lands",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "translate",
      "kind": "registry",
      "title": "Translate",
      "description": "Translate what you type, the selected text or the clipboard, with the language detected as you type. Alternatives, dictionary entries and romanisation included; uses Google Translate without a key, or DeepL with one.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰗊",
          "bg": "blue"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/translate@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/translate",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "translate",
        "title": "Translate",
        "description": "Translate what you type, the selected text or the clipboard, with the language detected as you type. Alternatives, dictionary entries and romanisation included; uses Google Translate without a key, or DeepL with one.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰗊",
            "bg": "blue"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "from",
            "label": "From",
            "description": "The source language as a code or a name (`en`, `turkish`); `auto` detects it. A prefix in the query (`en\u003etr`) overrides it once.",
            "placeholder": "auto",
            "default": "auto"
          },
          {
            "kind": "text",
            "id": "to",
            "label": "To",
            "description": "The target language as a code or a name; empty is the system language. Text already in it is translated the other way. A prefix (`tr:`, `\u003ede`) overrides it once.",
            "placeholder": "the system language",
            "default": ""
          },
          {
            "kind": "select",
            "id": "backend",
            "label": "Backend",
            "description": "Google is the web app's unofficial endpoint, no key, with alternatives and romanisation; DeepL needs a key (the free tier does) and answers the translation alone.",
            "options": [
              {
                "id": "google",
                "title": "Google Translate (no key, unofficial)"
              },
              {
                "id": "deepl",
                "title": "DeepL (needs a key)"
              }
            ],
            "default": "google"
          },
          {
            "kind": "secret",
            "id": "api_key",
            "required": true,
            "label": "DeepL API key",
            "only": {
              "backend": "deepl"
            },
            "description": "From deepl.com/your-account/keys; a free key ends in `:fx`. Only read when the backend is DeepL.",
            "placeholder": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:fx",
            "default": ""
          },
          {
            "kind": "boolean",
            "id": "speak",
            "label": "Speak on copy",
            "text": "Also read the translation aloud when Enter copies it (cmd+shift+s speaks either way)",
            "default": false
          }
        ],
        "store": {
          "tagline": "Translate typed, selected or copied text as you type",
          "category": "productivity",
          "features": [
            "Translates as you type, the source detected, into the language you set or the system's",
            "Name the target inline: `tr: hello`, `\u003ede hello`, `en\u003etr merhaba`; works at the root too",
            "With nothing typed, starts from the selected text or the newest clipboard text",
            "`enter` copies, `cmd+enter` pastes, `cmd+shift+s` reads it aloud; Swap translates the result back",
            "Alternatives, dictionary entries for a single word, and romanisation for non-Latin scripts",
            "Google Translate needs no key (unofficial, some networks are refused), or DeepL with a free key; a history of what you used"
          ],
          "permissions": [
            "network",
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-translate.png",
              "caption": "hello world typed with the system language Turkish: the translation first, the detected language, the alternatives, Swap"
            },
            {
              "file": "2-prefix.png",
              "caption": "tr\u003een merhaba dünya. Nasılsın?: both ends named in the prefix; the detail pane shows both texts and the pair"
            },
            {
              "file": "3-romanisation.png",
              "caption": "\u003eja hello: the Japanese with its romanisation and the dictionary entry"
            },
            {
              "file": "4-actions.png",
              "caption": "What a translation can do: copy, paste, speak, the source, Google Translate"
            },
            {
              "file": "5-history.png",
              "caption": "Translation History: what was copied or spoken, newest first"
            }
          ],
          "actions": [
            {
              "title": "Copy",
              "description": "The translation onto the clipboard; with `speak` on, read aloud too.",
              "keys": "enter"
            },
            {
              "title": "Paste",
              "description": "Hides, then pastes the translation into the app in front.",
              "keys": "cmd+enter"
            },
            {
              "title": "Speak",
              "description": "Reads the row aloud in its language: `say` with a voice of that language on macOS, `spd-say` or `espeak` on Linux.",
              "keys": "cmd+shift+s"
            },
            {
              "title": "Copy the source text",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Open in Google Translate",
              "description": "The pair and the text in the web app.",
              "keys": "cmd+o"
            },
            {
              "title": "Swap and translate",
              "description": "On the Swap row: the result translated back the other way.",
              "keys": "enter"
            },
            {
              "title": "Translate again",
              "description": "In the history: the entry's text translated afresh.",
              "keys": "cmd+t"
            },
            {
              "title": "Remove from history",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "translate": {
            "title": "Translate",
            "kind": "input",
            "inline": true,
            "match": "^\\s*(?:[a-z][a-z-]{1,24}\\s*\u003e\\s*[a-z][a-z-]{1,24}|\u003e[a-z][a-z-]{1,24}|[a-z][a-z-]{1,24}\\s*:)\\s+\\S",
            "description": "Type text and it is translated to the `to` language (or the system's) with the source detected; `tr: text`, `\u003ede text` or `en\u003etr text` name the ends once; nothing typed translates the selection, else the clipboard. At the root a prefixed query answers inline.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the translation (on Swap: translate it back)"
              },
              {
                "keys": "cmd+enter",
                "title": "Paste the translation into the app in front"
              },
              {
                "keys": "cmd+shift+s",
                "title": "Speak the row aloud"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the source text"
              },
              {
                "keys": "cmd+o",
                "title": "Open in Google Translate"
              }
            ]
          },
          "history": {
            "title": "Translation History",
            "kind": "live",
            "remember": false,
            "description": "Translations you copied, pasted or spoke, newest first; Enter copies the translation again.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy the translation"
              },
              {
                "keys": "cmd+enter",
                "title": "Paste the translation"
              },
              {
                "keys": "cmd+shift+s",
                "title": "Speak it"
              },
              {
                "keys": "cmd+t",
                "title": "Translate the entry again"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the source text"
              },
              {
                "keys": "cmd+d",
                "title": "Remove the entry"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/translate",
      "tagline": "Translate typed, selected or copied text as you type",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/translate/screenshots/1-translate-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/1-translate.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/2-prefix-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/2-prefix.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/3-romanisation-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/3-romanisation.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/5-history-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/5-history.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/translate/screenshots/1-translate.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/2-prefix.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/3-romanisation.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/4-actions.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/5-history.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/translate/screenshots/1-translate-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/2-prefix-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/3-romanisation-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/translate/screenshots/5-history-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "turkish",
      "kind": "registry",
      "title": "Turkish",
      "description": "Turkish text tools: put the Turkish letters back into text typed without them (Turkce yazilmis → Türkçe yazılmış), take them out again, and change case the Turkish way, where i and ı are two letters. Works on what you type or on the selection, pasting the result back over it.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰬴",
          "bg": "red"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/turkish@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/turkish",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "turkish",
        "title": "Turkish",
        "description": "Turkish text tools: put the Turkish letters back into text typed without them (Turkce yazilmis → Türkçe yazılmış), take them out again, and change case the Turkish way, where i and ı are two letters. Works on what you type or on the selection, pasting the result back over it.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰬴",
            "bg": "red"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "deasciify",
          "asciify",
          "türkçe",
          "turkce"
        ],
        "settings": [
          {
            "kind": "select",
            "id": "primary_action",
            "label": "Primary action",
            "description": "What Enter does on a row; the other is cmd+Enter, and cmd+c always copies.",
            "options": [
              {
                "id": "paste",
                "title": "Paste into the app in front"
              },
              {
                "id": "copy",
                "title": "Copy to the clipboard"
              }
            ],
            "default": "paste"
          }
        ],
        "store": {
          "tagline": "Restore Turkish letters (Turkce → Türkçe) and change case correctly",
          "category": "productivity",
          "features": [
            "Deasciify: letters restored from context (sik → sık, kus → kuş, acik → açık), using the Emacs turkish-mode table",
            "Asciify: the reverse, for forms that take no Turkish letters",
            "UPPERCASE, lowercase and Title Case the Turkish way (i ↔ İ, ı ↔ I); a suffix after an apostrophe stays down (İstanbul'da)",
            "Select text in any app and open the list: `enter` pastes the result over the selection",
            "`cmd+c` copies, `cmd+t` sends the result to Translate; each row says how many letters it changed",
            "`pal://turkish/deasciify?text=…` and the other conversions for scripts and hotkeys"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Paste",
              "description": "Into the app in front; over the selection when the rows came from it.",
              "keys": "enter"
            },
            {
              "title": "Copy",
              "keys": "cmd+c"
            },
            {
              "title": "Translate",
              "description": "The row's text in the Translate palette.",
              "keys": "cmd+t"
            },
            {
              "title": "Copy the source text",
              "keys": "cmd+shift+c"
            }
          ],
          "screenshots": [
            {
              "file": "1-selection.png",
              "caption": "Opened over a selected sentence: its Turkish letters back, the reverse and the three cases; Enter replaces the selection"
            },
            {
              "file": "2-detail.png",
              "caption": "cmd+i shows the result over the source, what changed and where the text came from"
            },
            {
              "file": "3-cases.png",
              "caption": "Typed Turkish: the cases keep i and ı apart (İSTANBUL, ILIK) and a suffix after an apostrophe stays down"
            },
            {
              "file": "4-actions.png",
              "caption": "Paste, copy, hand the row to Translate, or copy the source text"
            }
          ]
        },
        "links": {
          "deasciify": {
            "description": "Turkish letters restored (Turkce → Türkçe)",
            "params": {
              "text": {
                "description": "The text; the selection, else the clipboard, when absent"
              },
              "paste": {
                "description": "Paste the result into the app in front rather than copy it (the default over a selection)",
                "type": "boolean"
              }
            }
          },
          "asciify": {
            "description": "Turkish letters as ASCII (Türkçe → Turkce)",
            "params": {
              "text": {
                "description": "The text; the selection, else the clipboard, when absent"
              },
              "paste": {
                "description": "Paste rather than copy (the default over a selection)",
                "type": "boolean"
              }
            }
          },
          "upper": {
            "description": "Turkish uppercase (i → İ, ı → I)",
            "params": {
              "text": {
                "description": "The text; the selection, else the clipboard, when absent"
              },
              "paste": {
                "description": "Paste rather than copy (the default over a selection)",
                "type": "boolean"
              }
            }
          },
          "lower": {
            "description": "Turkish lowercase (I → ı, İ → i)",
            "params": {
              "text": {
                "description": "The text; the selection, else the clipboard, when absent"
              },
              "paste": {
                "description": "Paste rather than copy (the default over a selection)",
                "type": "boolean"
              }
            }
          },
          "title": {
            "description": "Title Case the Turkish way",
            "params": {
              "text": {
                "description": "The text; the selection, else the clipboard, when absent"
              },
              "paste": {
                "description": "Paste rather than copy (the default over a selection)",
                "type": "boolean"
              }
            }
          }
        },
        "palettes": {
          "turkish": {
            "title": "Turkish",
            "kind": "input",
            "description": "What you type (or the selection, else the clipboard) deasciified, asciified, and in the Turkish upper, lower and title cases; Enter pastes the row.",
            "keys": [
              {
                "keys": "enter",
                "title": "Paste into the app in front (over the selection the rows came from)"
              },
              {
                "keys": "cmd+enter",
                "title": "Copy"
              },
              {
                "keys": "cmd+c",
                "title": "Copy"
              },
              {
                "keys": "cmd+t",
                "title": "Translate the row"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the source text"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/turkish",
      "tagline": "Restore Turkish letters (Turkce → Türkçe) and change case correctly",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/turkish/screenshots/1-selection-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/1-selection.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/3-cases-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/3-cases.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/4-actions-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/4-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/turkish/screenshots/1-selection.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/3-cases.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/4-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/turkish/screenshots/1-selection-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/3-cases-dark.png",
        "https://pal.cagdas.io/extensions/turkish/screenshots/4-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "deasciify",
          "url": "pal://turkish/deasciify",
          "cli": "pal call turkish/deasciify",
          "description": "Turkish letters restored (Turkce → Türkçe)",
          "params": [
            {
              "name": "text",
              "description": "The text; the selection, else the clipboard, when absent"
            },
            {
              "name": "paste",
              "description": "Paste the result into the app in front rather than copy it (the default over a selection)",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "asciify",
          "url": "pal://turkish/asciify",
          "cli": "pal call turkish/asciify",
          "description": "Turkish letters as ASCII (Türkçe → Turkce)",
          "params": [
            {
              "name": "text",
              "description": "The text; the selection, else the clipboard, when absent"
            },
            {
              "name": "paste",
              "description": "Paste rather than copy (the default over a selection)",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "upper",
          "url": "pal://turkish/upper",
          "cli": "pal call turkish/upper",
          "description": "Turkish uppercase (i → İ, ı → I)",
          "params": [
            {
              "name": "text",
              "description": "The text; the selection, else the clipboard, when absent"
            },
            {
              "name": "paste",
              "description": "Paste rather than copy (the default over a selection)",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "lower",
          "url": "pal://turkish/lower",
          "cli": "pal call turkish/lower",
          "description": "Turkish lowercase (I → ı, İ → i)",
          "params": [
            {
              "name": "text",
              "description": "The text; the selection, else the clipboard, when absent"
            },
            {
              "name": "paste",
              "description": "Paste rather than copy (the default over a selection)",
              "type": "boolean"
            }
          ]
        },
        {
          "route": "title",
          "url": "pal://turkish/title",
          "cli": "pal call turkish/title",
          "description": "Title Case the Turkish way",
          "params": [
            {
              "name": "text",
              "description": "The text; the selection, else the clipboard, when absent"
            },
            {
              "name": "paste",
              "description": "Paste rather than copy (the default over a selection)",
              "type": "boolean"
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "typing",
      "kind": "registry",
      "title": "Typing",
      "description": "A typing test in the style of monkeytype: common English words, a smooth caret, timed, word-count or free tests, and a result with wpm, accuracy, consistency and a chart. Personal bests and every past test are kept, with a stats page to follow your progress.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰌌",
          "bg": "teal"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/typing@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/typing",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "typing",
        "title": "Typing",
        "description": "A typing test in the style of monkeytype: common English words, a smooth caret, timed, word-count or free tests, and a result with wpm, accuracy, consistency and a chart. Personal bests and every past test are kept, with a stats page to follow your progress.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰌌",
            "bg": "teal"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "sync": {
          "config": {
            "fields": {
              "mode": "latest",
              "time": "latest",
              "words": "latest",
              "punctuation": "latest",
              "numbers": "latest"
            }
          },
          "records": {
            "fields": {
              "best": "union",
              "history": "union",
              "tests": "sum",
              "secs": "sum"
            }
          }
        },
        "leaderboards": [
          {
            "id": "time/15",
            "title": "15 seconds",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "time/30",
            "title": "30 seconds",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "time/60",
            "title": "60 seconds",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "time/120",
            "title": "120 seconds",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "words/10",
            "title": "10 words",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "words/25",
            "title": "25 words",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "words/50",
            "title": "50 words",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          },
          {
            "id": "words/100",
            "title": "100 words",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 350
          }
        ],
        "store": {
          "tagline": "A monkeytype-style typing test with wpm, accuracy and personal bests",
          "category": "fun",
          "features": [
            "Common English words that scroll as you type, each letter marked right, wrong or extra",
            "Timed (15 to 120 seconds), by word count (10 to 100) or zen, with punctuation and numbers if you like",
            "A pace caret to race your best, average or last test; stop on error by letter or by word",
            "Results: wpm, accuracy, raw speed, consistency, and a second-by-second chart with the mistakes",
            "Personal bests per kind of test, the average of your last ten, and a stats page with a progress chart",
            "`tab` starts a new test any time; `r` on the result repeats the same words",
            "A leaderboard of words per minute for each plain time and word count; signed in, your bests and history follow you to your other machines and play.cagdas.io"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-test.png",
              "caption": "Mid-test: the caret on the next letter, a slip in red, the seconds left above"
            },
            {
              "file": "2-result.png",
              "caption": "The result: wpm and accuracy, the test second by second, a new best for ten words",
              "cover": [
                183,
                219,
                1001,
                491
              ]
            },
            {
              "file": "3-zen.png",
              "caption": "Zen: no words to follow, the caret after whatever you type; Enter ends it and scores it"
            },
            {
              "file": "4-stats.png",
              "caption": "Stats: the figures, and the progress chart with its average of ten"
            },
            {
              "file": "5-history.png",
              "caption": "Further down: the personal best at every length, and every test taken, newest first"
            }
          ],
          "actions": [
            {
              "title": "New test",
              "description": "New words, the same options; mid-test the test is dropped.",
              "keys": "tab"
            },
            {
              "title": "Repeat the test",
              "description": "The same words again, from the result.",
              "keys": "r"
            },
            {
              "title": "Stats and history",
              "description": "The stats button on the bar, S on the result, or cmd+k.",
              "keys": "s"
            },
            {
              "title": "Change the test",
              "description": "Before the first key: up and down switch time and words, left and right the length.",
              "keys": "up, down, left, right"
            }
          ],
          "play": true
        },
        "settings": [
          {
            "kind": "select",
            "id": "pace_caret",
            "label": "Pace caret",
            "description": "A second, fainter caret that moves at a steady speed for you to race: your personal best, the average of your last ten or your last test of the same kind (time 30, words 50 with punctuation, and so on). Nothing to race until you have finished one of that kind; never in zen. Also switched from ⌘K.",
            "options": [
              {
                "id": "off",
                "title": "Off"
              },
              {
                "id": "pb",
                "title": "Personal best"
              },
              {
                "id": "average",
                "title": "Average of the last 10"
              },
              {
                "id": "last",
                "title": "Last test"
              }
            ],
            "default": "off"
          },
          {
            "kind": "select",
            "id": "stop_on_error",
            "label": "Stop on error",
            "description": "Letter: a wrong letter is not typed, the caret waits for the right one. Word: a word with a mistake cannot be left with space until it is fixed. Either way the wrong key counts against accuracy. Also switched from ⌘K.",
            "options": [
              {
                "id": "off",
                "title": "Off"
              },
              {
                "id": "letter",
                "title": "Letter"
              },
              {
                "id": "word",
                "title": "Word"
              }
            ],
            "default": "off"
          },
          {
            "kind": "boolean",
            "id": "clock",
            "label": "Clock",
            "text": "Show the seconds while you type",
            "description": "The seconds left in a time test, or so far in zen. Off hides them: a time test still ends on time and the result shows how long it took. The word count of a words test stays. Also ⌘T or ⌘K.",
            "default": true
          }
        ],
        "palettes": {
          "typing": {
            "title": "Typing",
            "kind": "view",
            "description": "The test. Type the words (in zen, anything; Enter ends it); Tab starts a new one; Escape leaves (a test in progress is dropped).",
            "keys": [
              {
                "keys": "tab",
                "title": "New test"
              },
              {
                "keys": "enter",
                "title": "Zen: finish"
              },
              {
                "keys": "space",
                "title": "The next word; the letters left in this one are missed"
              },
              {
                "keys": "backspace",
                "title": "Take back a letter; at the start of a word, back into the one before if it was left wrong"
              },
              {
                "keys": "alt+backspace",
                "title": "Take back the word (ctrl+backspace too)"
              },
              {
                "keys": "left",
                "title": "Before the first key: a shorter test (right, a longer one)"
              },
              {
                "keys": "up",
                "title": "Before the first key: time, words or zen (down too)"
              },
              {
                "keys": "r",
                "title": "On the result: the same words again"
              },
              {
                "keys": "enter",
                "title": "On the result: a new test"
              },
              {
                "keys": "s",
                "title": "On the result: stats and history (tab, enter or s again closes them)"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/typing",
      "tagline": "A monkeytype-style typing test with wpm, accuracy and personal bests",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/typing/screenshots/1-test-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/1-test.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/2-result-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/2-result.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/3-zen-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/3-zen.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/4-stats-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/4-stats.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/5-history-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/5-history.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/typing/screenshots/1-test.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/2-result.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/3-zen.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/4-stats.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/5-history.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/typing/screenshots/1-test-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/2-result-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/3-zen-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/4-stats-dark.png",
        "https://pal.cagdas.io/extensions/typing/screenshots/5-history-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "unicode",
      "kind": "bundled",
      "title": "Unicode Characters",
      "description": "Arrows, math, currency, punctuation, keyboard symbols, box drawing, Greek and accented letters in a grid to copy or paste. Search by name, alias, HTML entity, LaTeX command or code point.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰏉",
          "bg": "pink"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/unicode@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/unicode",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "unicode",
        "title": "Unicode Characters",
        "description": "Arrows, math, currency, punctuation, keyboard symbols, box drawing, Greek and accented letters in a grid to copy or paste. Search by name, alias, HTML entity, LaTeX command or code point.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰏉",
            "bg": "pink"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [],
        "store": {
          "tagline": "Arrows, math, currency, dashes and keyboard glyphs to paste",
          "category": "reference",
          "features": [
            "About 1,800 characters in sections: arrows, math, Greek, currency, quotes and dashes, fractions, Mac keys (⌘ ⌥ ⇧ ⌃), box drawing",
            "Search by name, code point (`2192`), HTML entity (`rarr`), LaTeX (`\\alpha`) or a plain word (`cmd`, `tick`, `eur`)",
            "`enter` copies the character, `cmd+enter` pastes it into the app in front",
            "Copy the code point (`U+2192`), the HTML entity (`\u0026rarr;`) or the numeric reference instead",
            "A detail pane with the name and the character large, its block, UTF-8 bytes, LaTeX command and aliases",
            "The last twelve copied lead in a Recent section"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-grid.png",
              "caption": "The ones copied lately first, then every character in a grid by block; the full name of the one under the cursor below"
            },
            {
              "file": "2-search.png",
              "caption": "Searching arrow: the matches in every block, the recent ones first"
            },
            {
              "file": "3-actions.png",
              "caption": "Copy or paste the character, or copy its code point, HTML entity or numeric reference"
            }
          ],
          "actions": [
            {
              "title": "Copy character",
              "keys": "enter"
            },
            {
              "title": "Paste",
              "description": "Into the app that was in front; needs Accessibility on macOS.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy code point",
              "description": "`U+2192`",
              "keys": "cmd+shift+u"
            },
            {
              "title": "Copy HTML entity",
              "description": "`\u0026rarr;`, or `\u0026#x2192;` for a character without a named entity.",
              "keys": "cmd+shift+e"
            },
            {
              "title": "Copy numeric reference",
              "description": "`\u0026#x2192;`",
              "keys": "cmd+shift+n"
            }
          ]
        },
        "palettes": {
          "unicode": {
            "title": "Unicode Characters",
            "tier": "catalog",
            "kind": "grid",
            "description": "The bundled character table, by block; recently copied characters first.",
            "keys": [
              {
                "keys": "enter",
                "title": "Copy character"
              },
              {
                "keys": "cmd+enter",
                "title": "Paste"
              },
              {
                "keys": "cmd+shift+u",
                "title": "Copy code point"
              },
              {
                "keys": "cmd+shift+e",
                "title": "Copy HTML entity"
              },
              {
                "keys": "cmd+shift+n",
                "title": "Copy numeric reference"
              }
            ],
            "settings": [
              {
                "kind": "number",
                "id": "columns",
                "label": "Columns",
                "description": "Tiles per row in the grid.",
                "min": 4,
                "max": 16,
                "default": 10
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/unicode",
      "tagline": "Arrows, math, currency, dashes and keyboard glyphs to paste",
      "category": "reference",
      "screenshots": [
        "https://pal.cagdas.io/extensions/unicode/screenshots/1-grid-dark.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/1-grid.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/3-actions.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/unicode/screenshots/1-grid.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/3-actions.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/unicode/screenshots/1-grid-dark.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/unicode/screenshots/3-actions-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "vortex",
      "kind": "registry",
      "title": "Vortex",
      "description": "Turn round the centre and slip through the gaps as walls close in on the beat. Six stages written to their own songs, each in a world of its own, and a hyper of each; race the ghost of your best, medals that open new looks, Endless, a daily run, practice from any rank, and a retry one key away.",
      "version": "1.0.0",
      "icon": {
        "tile": {
          "svg": "M15 8l-3.5 6.06h-7L1 8l3.5-6.06h7zM12.4 8l-2.2-3.8H5.8L3.6 8l2.2 3.8h4.4zM8 5.6l2.2 3.9H5.8z",
          "bg": "blue"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/vortex@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/vortex",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "vortex",
        "title": "Vortex",
        "description": "Turn round the centre and slip through the gaps as walls close in on the beat. Six stages written to their own songs, each in a world of its own, and a hyper of each; race the ghost of your best, medals that open new looks, Endless, a daily run, practice from any rank, and a retry one key away.",
        "version": "1.0.0",
        "icon": {
          "tile": {
            "svg": "M15 8l-3.5 6.06h-7L1 8l3.5-6.06h7zM12.4 8l-2.2-3.8H5.8L3.6 8l2.2 3.8h4.4zM8 5.6l2.2 3.9H5.8z",
            "bg": "blue"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "keywords": [
          "hexagon",
          "rhythm",
          "arcade",
          "reflex"
        ],
        "settings": [
          {
            "id": "volume",
            "label": "Volume",
            "kind": "number",
            "description": "How loud the music and the sounds are; M in the game turns them off.",
            "min": 0,
            "max": 100,
            "step": 5,
            "unit": "%",
            "slider": true,
            "default": 80
          }
        ],
        "sync": {
          "save": {
            "fields": {
              "v": "max",
              "boards": {
                "fields": {
                  "pulse": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "drift": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "prism": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "undertow": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "overdrive": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "singularity": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "pulse+": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "drift+": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "prism+": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "undertow+": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "overdrive+": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "singularity+": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  },
                  "endless": {
                    "fields": {
                      "best": "max",
                      "tries": "sum",
                      "time": "sum",
                      "medals": "union"
                    }
                  }
                }
              },
              "ghosts": {
                "fields": {
                  "pulse": "latest",
                  "drift": "latest",
                  "prism": "latest",
                  "undertow": "latest",
                  "overdrive": "latest",
                  "singularity": "latest",
                  "pulse+": "latest",
                  "drift+": "latest",
                  "prism+": "latest",
                  "undertow+": "latest",
                  "overdrive+": "latest",
                  "singularity+": "latest"
                }
              },
              "daily": {
                "fields": {
                  "best": "max",
                  "tries": "max"
                }
              },
              "last": "latest",
              "muted": "latest",
              "skin": "latest",
              "trail": "latest",
              "ghost": "latest"
            }
          },
          "scene": "local"
        },
        "leaderboards": [
          {
            "id": "stage/pulse",
            "title": "Pulse",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "stage/drift",
            "title": "Drift",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "stage/prism",
            "title": "Prism",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "stage/undertow",
            "title": "Undertow",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "stage/overdrive",
            "title": "Overdrive",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "stage/singularity",
            "title": "Singularity",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "hyper/pulse",
            "title": "Pulse Hyper",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "hyper/drift",
            "title": "Drift Hyper",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "hyper/prism",
            "title": "Prism Hyper",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "hyper/undertow",
            "title": "Undertow Hyper",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "hyper/overdrive",
            "title": "Overdrive Hyper",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "hyper/singularity",
            "title": "Singularity Hyper",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 3600
          },
          {
            "id": "endless",
            "title": "Endless",
            "order": "desc",
            "format": "time",
            "min": 0,
            "max": 36000
          },
          {
            "id": "daily",
            "title": "Daily",
            "order": "desc",
            "format": "time",
            "period": "day",
            "min": 0,
            "max": 3600
          }
        ],
        "store": {
          "tagline": "Slip through the closing walls, on the beat",
          "category": "fun",
          "play": true,
          "platforms": [
            "macos",
            "linux"
          ],
          "actions": [
            {
              "title": "Turn",
              "description": "Round the centre, either way; A and D too. Hold Shift to turn slowly for a fine line.",
              "keys": "left, right"
            },
            {
              "title": "Play, or play again",
              "description": "After a death the next run is one key away.",
              "keys": "space"
            },
            {
              "title": "Choose a stage",
              "description": "Left and right on the stages; up for a stage's hyper once you've cleared it.",
              "keys": "left, right, up"
            },
            {
              "title": "Practice",
              "description": "On a stage: start from a rank you've reached there.",
              "keys": "p"
            },
            {
              "title": "Your look",
              "description": "The player's shape and trail, opened by medals; the ghost on or off.",
              "keys": "c"
            },
            {
              "title": "Back to the stages",
              "keys": "backspace"
            },
            {
              "title": "Sound on or off",
              "keys": "m"
            }
          ],
          "features": [
            "Walls close in on the centre with one way through; turn to the gap before they reach you, while the world spins, reverses and changes shape",
            "Six stages written to their songs: walls land on the beat, builds tighten and go dark, every drop hits with a slam on its downbeat",
            "Each stage its own world: neon, a nebula, glass, deep water, acid speed, a black hole; and a hyper of each, faster and in other colours",
            "Race the ghost of your best run, see what killed you again in slow motion, hear every near miss",
            "Medals for clearing, for a steady hand and for near misses, which open new shapes and trails for the player",
            "Endless (every stage in turn, then their hypers), a daily run with the same walls for everyone, and practice from any rank you've reached",
            "A leaderboard for every stage and its hyper, Endless and the daily; signed in, your bests, medals and looks follow you to your other machines and play.cagdas.io"
          ],
          "screenshots": [
            {
              "file": "1-pulse.png",
              "caption": "Pulse: a neon grid far below, walls that read at a glance, and you, racing a minute against the song"
            },
            {
              "file": "2-undertow.png",
              "caption": "Undertow: caustics and bubbles under a half-time song, the moment a record falls",
              "cover": [
                241,
                260,
                958,
                470
              ]
            },
            {
              "file": "3-singularity.png",
              "caption": "Singularity in hyper: a black hole at the centre, the last stage, faster"
            },
            {
              "file": "4-over.png",
              "caption": "A death replays slowly with the wall that got you outlined; the card says how close the record and the next rank were"
            },
            {
              "file": "5-title.png",
              "caption": "The stages, each playing itself behind its card: your best, its rank, your medals, practice from a rank you reached"
            },
            {
              "file": "6-look.png",
              "caption": "Medals open new shapes and trails for the player; the ghost of your best run, on or off"
            }
          ]
        },
        "palettes": {
          "vortex": {
            "title": "Vortex",
            "kind": "view",
            "description": "Turn round the centre through the closing walls. Escape or closing the panel pauses a run.",
            "keys": [
              {
                "keys": "left",
                "title": "Turn (arrows or A and D; Shift turns slowly)"
              },
              {
                "keys": "space",
                "title": "Play, or play again"
              },
              {
                "keys": "up",
                "title": "Hyper, on the stages"
              },
              {
                "keys": "p",
                "title": "Practice from a rank, on the stages"
              },
              {
                "keys": "c",
                "title": "Your look, on the stages"
              },
              {
                "keys": "backspace",
                "title": "Back to the stages"
              },
              {
                "keys": "m",
                "title": "Sound on or off"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/vortex",
      "tagline": "Slip through the closing walls, on the beat",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/vortex/screenshots/1-pulse-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/1-pulse.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/2-undertow-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/2-undertow.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/3-singularity-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/3-singularity.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/4-over-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/4-over.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/5-title-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/5-title.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/6-look-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/6-look.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/vortex/screenshots/1-pulse.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/2-undertow.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/3-singularity.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/4-over.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/5-title.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/6-look.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/vortex/screenshots/1-pulse-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/2-undertow-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/3-singularity-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/4-over-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/5-title-dark.png",
        "https://pal.cagdas.io/extensions/vortex/screenshots/6-look-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "weather",
      "kind": "registry",
      "title": "Weather",
      "description": "Local weather from Open-Meteo, with no account or key: a live sky with the next hours and the week ahead, and a bar item that stays out of the way in ordinary weather and shows up for rain, fog, wind or uncomfortable temperatures.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰖙",
          "bg": "cyan"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/weather@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/weather",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "weather",
        "title": "Weather",
        "description": "Local weather from Open-Meteo, with no account or key: a live sky with the next hours and the week ahead, and a bar item that stays out of the way in ordinary weather and shows up for rain, fog, wind or uncomfortable temperatures.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰖙",
            "bg": "cyan"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "location",
            "label": "Location",
            "description": "A place name, optionally narrowed by region or country: “Istanbul”, “London, Ontario”, “Paris, Texas”. Only the first part is searched; the rest choose between same-named places. Resolved privately by Open-Meteo's location search. The palette's L key searches and sets it too.",
            "placeholder": "Istanbul, Turkey",
            "default": ""
          }
        ],
        "palettes": {
          "weather": {
            "title": "Weather",
            "kind": "view",
            "description": "The weather where you are over a live sky: the reading now with its picture, what is coming over the next hours, and the days ahead with each one's span.",
            "keywords": [
              "weather",
              "forecast",
              "temperature",
              "rain"
            ],
            "keys": [
              {
                "keys": "left",
                "title": "An hour earlier (shift: three)"
              },
              {
                "keys": "right",
                "title": "An hour later (shift: three)"
              },
              {
                "keys": "up",
                "title": "The day before; its hours fill the row"
              },
              {
                "keys": "down",
                "title": "The day after; its hours fill the row"
              },
              {
                "keys": "n",
                "title": "Back to now"
              },
              {
                "keys": "l",
                "title": "Search for a place and keep it"
              },
              {
                "keys": "o",
                "title": "Open the place in Maps"
              },
              {
                "keys": "r",
                "title": "Read the forecast again now"
              }
            ]
          }
        },
        "states": {
          "temp": {
            "description": "The temperature now, in the service's unit",
            "kind": "number"
          },
          "code": {
            "description": "The WMO weather code now",
            "kind": "number"
          },
          "quiet": {
            "description": "A clear or cloudy sky (WMO 0 to 3): nothing falling, no fog",
            "kind": "boolean"
          },
          "condition": {
            "description": "The condition's name",
            "kind": "string"
          },
          "rain_in": {
            "description": "Hours until rain is likely (a wet hour, or a chance of half or more) within the next day; 0 while it rains, unknown when none comes",
            "kind": "number"
          }
        },
        "bar": {
          "weather": {
            "title": "Weather",
            "description": "A quiet condition-led weather signal: hidden by its rules in ordinary weather (a quiet sky between 10 and 30 degrees), visible for rain now or likely within 12 hours, fog, wind or temperatures outside that band, blue when cold and red when hot. The popover is the forecast: the reading now on a card tinted by the sky, humidity, wind, UV and the next sunrise or sunset, the next eight hours, then five days with each day's span against theirs.",
            "refresh": {
              "every": 600,
              "on": [
                "wake",
                "network"
              ]
            },
            "mocks": {
              "clear": {
                "title": "Clear, a listed notable condition",
                "item": {
                  "icon": "󰖙",
                  "title": "22°C",
                  "color": "amber",
                  "tooltip": "Clear in Istanbul"
                }
              },
              "cold": {
                "title": "Cold",
                "item": {
                  "icon": "󰖐",
                  "title": "3°C",
                  "color": "blue",
                  "tooltip": "Overcast in Istanbul"
                }
              },
              "rain": {
                "title": "Rain",
                "item": {
                  "icon": "󰖗",
                  "title": "14°C",
                  "color": "blue",
                  "tooltip": "Rain in Istanbul"
                }
              },
              "heat": {
                "title": "Hot",
                "item": {
                  "icon": "󰖙",
                  "title": "34°C",
                  "color": "red",
                  "tooltip": "Clear in Istanbul"
                }
              },
              "fog": {
                "title": "Fog",
                "item": {
                  "icon": "󰖑",
                  "title": "12°C",
                  "color": "teal",
                  "tooltip": "Fog in Istanbul"
                }
              },
              "quiet": {
                "title": "Ordinary weather",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰖕",
                    "title": "19°C",
                    "tooltip": "Partly cloudy in Istanbul"
                  }
                }
              },
              "unavailable": {
                "title": "Weather unavailable",
                "item": {
                  "icon": "󰖪",
                  "title": "Weather",
                  "color": "red",
                  "stale": true,
                  "tooltip": "Weather service did not answer"
                }
              },
              "soon": {
                "title": "Rain coming",
                "item": {
                  "icon": "󰖗",
                  "title": "14°C",
                  "color": "blue",
                  "tooltip": "Overcast in Istanbul · rain likely around 06:00"
                }
              }
            },
            "keys": [
              {
                "keys": "o",
                "title": "Open the place in Maps"
              },
              {
                "keys": "r",
                "title": "Read the forecast again now"
              }
            ],
            "rules": [
              {
                "id": "ordinary",
                "when": "weather.quiet and weather.temp \u003e= 10 and weather.temp \u003c= 30 and not (weather.rain_in \u003c= 12)",
                "description": "A quiet sky inside the comfort band with no rain likely in the next 12 hours: off the strip (move the band or the window here).",
                "hidden": true,
                "color": "muted"
              },
              {
                "id": "rain_soon",
                "when": "weather.quiet and weather.rain_in \u003c= 12",
                "description": "Rain likely within 12 hours while the sky is still dry: the rain glyph, in blue.",
                "icon": "󰖗",
                "color": "blue"
              },
              {
                "id": "cold",
                "when": "weather.temp \u003c 10",
                "description": "Below the comfort band.",
                "color": "blue"
              },
              {
                "id": "hot",
                "when": "weather.temp \u003e 30",
                "description": "Above the comfort band.",
                "color": "red"
              }
            ]
          }
        },
        "store": {
          "tagline": "A live sky with the weather where you are, and a bar item only when it is worth noticing",
          "category": "system",
          "features": [
            "The reading now with its own picture, over a sky drawn live from the forecast: clouds by cover drifting with the wind, sunset colours, stars, rain, snow, fog and lightning",
            "One plain sentence on what is coming, then the next hours with sunrise and sunset in their place",
            "The days ahead with each one's span against the others, today's reading marked on it",
            "Pick a day and its hours fill the row; walk the hours and the sky turns to each one",
            "Opens at once on the last reading and refreshes behind it; search for a place right in the palette",
            "The bar item hides in ordinary weather and comes back for rain now or within 12 hours, fog, wind, heat or cold"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-now.png",
              "caption": "Showers over Istanbul: the reading with its picture, when the rain eases, the next hours and the days ahead"
            },
            {
              "file": "2-later.png",
              "caption": "The arrows walk the hours: at nine the rain has gone and the sky turns to night"
            },
            {
              "file": "3-days.png",
              "caption": "Down picks a day: Friday's hours fill the row, and its clear sky takes over"
            },
            {
              "file": "4-storm.png",
              "caption": "A thunderstorm: heavy rain blown by the wind, lightning now and then"
            },
            {
              "file": "5-place.png",
              "caption": "L searches for a place and keeps it"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar only when the weather is worth a look: a shower passing, its glyph and the temperature in blue",
              "kind": "bar"
            },
            {
              "file": "bar-menubar-storm.png",
              "caption": "A thunderstorm turns it red",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: the reading on a card tinted by the sky, the next eight hours, five days with each day's span",
              "kind": "bar",
              "box": [
                418,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the weather glyph and the temperature",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open map",
              "description": "Open the place in Maps.",
              "keys": "o"
            },
            {
              "title": "Change place",
              "description": "Search for a place and keep it.",
              "keys": "l"
            },
            {
              "title": "Refresh",
              "description": "Read the forecast again now.",
              "keys": "r"
            },
            {
              "title": "Back to now",
              "description": "Return the hours and the sky to the present.",
              "keys": "n"
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/weather",
      "tagline": "A live sky with the weather where you are, and a bar item only when it is worth noticing",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/weather/screenshots/1-now-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/1-now.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/2-later-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/2-later.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/3-days-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/3-days.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/4-storm-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/4-storm.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/5-place-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/5-place.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar-storm-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar-storm.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/weather/screenshots/1-now.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/2-later.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/3-days.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/4-storm.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/5-place.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar-storm.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/weather/screenshots/1-now-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/2-later-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/3-days-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/4-storm-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/5-place-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar-storm-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/weather/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "weather",
          "title": "Weather",
          "description": "A quiet condition-led weather signal: hidden by its rules in ordinary weather (a quiet sky between 10 and 30 degrees), visible for rain now or likely within 12 hours, fog, wind or temperatures outside that band, blue when cold and red when hot. The popover is the forecast: the reading now on a card tinted by the sky, humidity, wind, UV and the next sunrise or sunset, the next eight hours, then five days with each day's span against theirs.",
          "refresh": {
            "every": 600,
            "on": [
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 10 min, on wake, when the network is back"
        }
      ],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "whatsapp",
      "kind": "registry",
      "title": "WhatsApp",
      "description": "Your WhatsApp chats in the panel through a self-hosted OpenWA gateway: recent chats with the unread ones first, full-text search over your whole history, and your contacts. Reading is always on; sending and reacting only if you turn it on.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z",
          "box": 24,
          "bg": "#25D366"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/whatsapp@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/whatsapp",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "whatsapp",
        "title": "WhatsApp",
        "description": "Your WhatsApp chats in the panel through a self-hosted OpenWA gateway: recent chats with the unread ones first, full-text search over your whole history, and your contacts. Reading is always on; sending and reacting only if you turn it on.",
        "keywords": [
          "wa"
        ],
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z",
            "box": 24,
            "bg": "#25D366"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "text",
            "id": "base_url",
            "label": "OpenWA URL",
            "description": "Where the OpenWA gateway answers (its /api is under it). The owner's runs at http://wp.lan; a generic install is http://localhost:3000.",
            "placeholder": "http://wp.lan",
            "default": "http://wp.lan"
          },
          {
            "kind": "secret",
            "id": "api_key",
            "required": true,
            "label": "API key",
            "description": "A key from OpenWA's Settings, API keys, sent as x-api-key. Kept in the OS keychain; the file holds a reference.",
            "placeholder": "owa_...",
            "default": ""
          },
          {
            "kind": "text",
            "id": "session",
            "label": "Session",
            "description": "The OpenWA session's name (the UUID it resolves to is cached); the one your phone is linked to.",
            "placeholder": "main",
            "default": "main"
          },
          {
            "kind": "boolean",
            "id": "send",
            "label": "Send",
            "text": "Send messages, reply and react from pal",
            "description": "Off (the default) leaves WhatsApp read and mark-read only: no message field, no reply, no reaction, whatever the key could do. On adds Send a message (the text typed in the bar, or a form) and React to a chat row and the reply field to the bar popover; nothing is sent without your text.",
            "default": false
          },
          {
            "kind": "select",
            "id": "open",
            "label": "Open chats in",
            "description": "auto opens the desktop app when it is installed (macOS) and the web client otherwise. A group has no link of its own, so it opens WhatsApp at the top either way.",
            "options": [
              {
                "id": "auto",
                "title": "The desktop app when installed, else the web client"
              },
              {
                "id": "app",
                "title": "The desktop app (whatsapp://)"
              },
              {
                "id": "web",
                "title": "The web client (web.whatsapp.com)"
              }
            ],
            "default": "auto"
          }
        ],
        "palettes": {
          "chats": {
            "title": "Chats",
            "description": "Every chat, unread first then newest first, with the picture, the newest message and who sent it, the unread count, the time; the pane is the last twenty messages as a conversation.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "tier": "primary",
            "rank": 10,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the chat (a group opens WhatsApp at the top)"
              },
              {
                "keys": "cmd+enter",
                "title": "Mark as read (Mark as unread on a read chat)"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Send a message typed in the bar (send on)"
              },
              {
                "keys": "cmd+shift+e",
                "title": "React to the latest message (send on)"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in the web client"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the number (the name of a group)"
              }
            ]
          },
          "unread": {
            "title": "Unread",
            "description": "Only the chats with something unread, direct messages then groups; the same rows and keys as Chats.",
            "kind": "live",
            "remember": false,
            "lazy": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Open the chat"
              },
              {
                "keys": "cmd+enter",
                "title": "Mark as read"
              },
              {
                "keys": "cmd+shift+r",
                "title": "Send a message typed in the bar (send on)"
              },
              {
                "keys": "cmd+shift+e",
                "title": "React to the latest message (send on)"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open in the web client"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the number (the name of a group)"
              }
            ]
          },
          "search": {
            "title": "Search WhatsApp",
            "description": "Full-text search over the archive (every message back to the first chat): the matching line, who said it where, and when.",
            "kind": "input",
            "keys": [
              {
                "keys": "enter",
                "title": "Open the chat"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the message"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the chat in the web client"
              }
            ]
          },
          "contacts": {
            "title": "Contacts",
            "description": "Every saved contact with the number; open a chat, copy the number, copy a vCard.",
            "kind": "list",
            "lazy": true,
            "ttl": 3600,
            "tier": "catalog",
            "keys": [
              {
                "keys": "enter",
                "title": "Open a chat with the contact"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the number"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy as a vCard"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the chat in the web client"
              }
            ]
          }
        },
        "states": {
          "unread": {
            "description": "Chats with unread messages",
            "kind": "number"
          },
          "direct": {
            "description": "Direct chats among them",
            "kind": "number"
          }
        },
        "bar": {
          "unread": {
            "title": "Unread",
            "description": "The number of unread chats as a badge, hidden at zero, red while a direct chat waits; the popover lists them with the picture, the newest message and the time, opens, marks read and (send on) replies from the keys.",
            "refresh": {
              "every": 30,
              "on": [
                "show",
                "wake",
                "network"
              ]
            },
            "mocks": {
              "groups": {
                "title": "Unread groups only",
                "item": {
                  "icon": "󰖣",
                  "badge": 2,
                  "urgent": false,
                  "tooltip": "2 chats unread: 2 groups"
                }
              },
              "direct": {
                "title": "A direct chat waits",
                "item": {
                  "icon": "󰖣",
                  "badge": 3,
                  "urgent": true,
                  "tooltip": "3 chats unread: 1 direct message, 2 groups"
                }
              },
              "one": {
                "title": "One unread chat",
                "item": {
                  "icon": "󰖣",
                  "badge": 1,
                  "urgent": true,
                  "tooltip": "1 chat unread: 1 direct message"
                }
              },
              "clear": {
                "title": "Nothing unread",
                "item": {
                  "hidden": true,
                  "empty": {
                    "icon": "󰖣",
                    "tooltip": "Nothing unread"
                  }
                }
              },
              "out": {
                "title": "No gateway key",
                "item": {
                  "hidden": true
                }
              }
            },
            "keys": [
              {
                "keys": "enter",
                "title": "Open the row's chat"
              },
              {
                "keys": "up",
                "title": "Move the cursor (down, j, k too; a click sets it)"
              },
              {
                "keys": "r",
                "title": "Reply: the search row becomes the field, Enter sends (send on)"
              },
              {
                "keys": "m",
                "title": "Mark the row read"
              },
              {
                "keys": "a",
                "title": "Mark all read (cmd+shift+a too)"
              },
              {
                "keys": "o",
                "title": "Open WhatsApp"
              },
              {
                "keys": "p",
                "title": "Open the Unread palette"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the row's chat in the web client"
              }
            ],
            "rules": [
              {
                "id": "quiet",
                "when": "whatsapp.unread == 0",
                "description": "Nothing unread: off the strip, muted for anyone who keeps it.",
                "hidden": true,
                "color": "muted"
              },
              {
                "id": "dm",
                "when": "whatsapp.direct \u003e 0",
                "description": "A direct message waits.",
                "urgent": true
              }
            ]
          }
        },
        "links": {
          "open": {
            "description": "Open a chat",
            "params": {
              "chat": {
                "description": "A chat id (…@c.us, …@lid, …@g.us), a phone number, or a name from the chats or the contacts",
                "required": true
              }
            }
          },
          "search": {
            "description": "Search the archive",
            "params": {
              "q": {
                "description": "Words from any message",
                "required": true
              }
            }
          }
        },
        "store": {
          "tagline": "Your WhatsApp chats, search and contacts in the panel",
          "category": "integration",
          "features": [
            "Chats newest first, unread on top, with the latest message, who sent it and the unread count",
            "`enter` opens the chat in WhatsApp, `cmd+enter` marks it read; the side pane shows the last twenty messages",
            "Full-text search across your whole archive, with who said it, where and when",
            "Contacts with their numbers: open a chat, copy the number or a vCard",
            "A bar item counting unread chats, hidden at zero and red while a direct chat waits; `space` in its popover reads a chat, `i` ignores it until the next message without the blue ticks",
            "Sending, replying and reacting stay off until you turn them on; your chats go only to your own gateway"
          ],
          "permissions": [
            "network",
            "token"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-chats.png",
              "caption": "Chats: unread first, the picture, the newest message and who sent it, the count, the time"
            },
            {
              "file": "2-detail.png",
              "caption": "The pane: the last messages as a conversation, a quoted reply indented, a photo as [photo]"
            },
            {
              "file": "3-unread.png",
              "caption": "Unread: direct messages then groups, the same keys"
            },
            {
              "file": "4-search.png",
              "caption": "Search WhatsApp: the matching line, who said it where, when"
            },
            {
              "file": "5-contacts.png",
              "caption": "Contacts: each name with its number, a number alone when it has none; copy it or a vCard"
            },
            {
              "file": "6-message.png",
              "caption": "Send a message (send on): a form for the text, the latest message there to quote"
            },
            {
              "file": "bar-menubar.png",
              "caption": "On the menu bar: the WhatsApp glyph with the count of unread chats, red while a direct message waits",
              "kind": "bar"
            },
            {
              "file": "bar-popover.png",
              "caption": "A click opens the popover: direct messages then groups with the picture, the newest message and the time, the keys",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                718
              ]
            },
            {
              "file": "bar-popover-preview.png",
              "caption": "Space reads the chat before deciding: the latest messages, with Enter, r and m still working there",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                960
              ]
            },
            {
              "file": "bar-popover-reply.png",
              "caption": "r turns the search row into a message field (send on); Enter sends it",
              "kind": "bar",
              "box": [
                434,
                64,
                840,
                718
              ]
            },
            {
              "file": "bar-sketchybar.png",
              "caption": "On sketchybar: the glyph and the count",
              "kind": "bar"
            }
          ],
          "actions": [
            {
              "title": "Open chat",
              "description": "In the desktop app (whatsapp://send?phone=) or the web client; a group opens WhatsApp at the top.",
              "keys": "enter"
            },
            {
              "title": "Mark as read",
              "description": "Mark as unread on a read chat; works on marked rows too.",
              "keys": "cmd+enter"
            },
            {
              "title": "Send a message",
              "description": "The text typed in the bar (the row's argument), a Reply choice quoting the latest message; a form when picked without it; send on only.",
              "keys": "cmd+shift+r"
            },
            {
              "title": "React to the latest message",
              "description": "One of WhatsApp's six quick reactions, or remove yours; send on only.",
              "keys": "cmd+shift+e"
            },
            {
              "title": "Open in the web client",
              "keys": "cmd+shift+o"
            },
            {
              "title": "Copy number",
              "description": "Copy name on a group.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy message",
              "description": "On a search hit.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy as vCard",
              "description": "On a contact.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Open WhatsApp settings",
              "description": "On a hint row: the extension's settings."
            }
          ]
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/whatsapp",
      "tagline": "Your WhatsApp chats, search and contacts in the panel",
      "category": "integration",
      "screenshots": [
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/1-chats-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/1-chats.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/3-unread-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/3-unread.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/4-search-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/4-search.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/5-contacts-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/5-contacts.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/6-message-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/6-message.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-preview-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-preview.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-reply-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-reply.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-sketchybar-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/1-chats.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/2-detail.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/3-unread.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/4-search.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/5-contacts.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/6-message.png"
      ],
      "bar_screenshots": [
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-menubar.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-preview.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-reply.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-sketchybar.png"
      ],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/1-chats-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/2-detail-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/3-unread-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/4-search-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/5-contacts-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/6-message-dark.png"
      ],
      "bar_screenshots_dark": [
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-menubar-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-preview-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-reply-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-popover-dark.png",
        "https://pal.cagdas.io/extensions/whatsapp/screenshots/bar-sketchybar-dark.png"
      ],
      "has_bar": true,
      "bar_items": [
        {
          "id": "unread",
          "title": "Unread",
          "description": "The number of unread chats as a badge, hidden at zero, red while a direct chat waits; the popover lists them with the picture, the newest message and the time, opens, marks read and (send on) replies from the keys.",
          "refresh": {
            "every": 30,
            "on": [
              "show",
              "wake",
              "network"
            ]
          },
          "refresh_words": "every 30s, when the panel shows, on wake, when the network is back"
        }
      ],
      "has_links": true,
      "links": [
        {
          "route": "open",
          "url": "pal://whatsapp/open?chat=\u003cchat\u003e",
          "cli": "pal call whatsapp/open chat=\u003cchat\u003e",
          "description": "Open a chat",
          "params": [
            {
              "name": "chat",
              "description": "A chat id (…@c.us, …@lid, …@g.us), a phone number, or a name from the chats or the contacts",
              "required": true
            }
          ]
        },
        {
          "route": "search",
          "url": "pal://whatsapp/search?q=\u003cq\u003e",
          "cli": "pal call whatsapp/search q=\u003cq\u003e",
          "description": "Search the archive",
          "params": [
            {
              "name": "q",
              "description": "Words from any message",
              "required": true
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "wifi",
      "kind": "bundled",
      "title": "Wi-Fi",
      "description": "The current network, the saved ones and what is in range: join, forget, copy the password, turn Wi-Fi off.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰖩",
          "bg": "blue"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/wifi@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/wifi",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "wifi",
        "title": "Wi-Fi",
        "description": "The current network, the saved ones and what is in range: join, forget, copy the password, turn Wi-Fi off.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰖩",
            "bg": "blue"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "store": {
          "tagline": "Join, forget or inspect Wi-Fi networks; switch the radio",
          "category": "system",
          "features": [
            "Current, Known and Available sections, with signal, channel, security and IP for the network you are on; `cmd+i` shows a network as a page",
            "`enter` joins a network, asking for the password in the search bar when it needs one",
            "`cmd+shift+c` copies a saved network's password (macOS asks for your keychain)",
            "`ctrl+x` forgets a network after a confirm; `cmd+c` copies the name or IP",
            "Turn Wi-Fi off or on, and scan for networks on macOS",
            "On macOS network names need Location access; it asks once, only when you open the list"
          ],
          "permissions": [
            "location",
            "nmcli"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-networks.png",
              "caption": "The current network with its address and signal, the saved ones, then what is in range"
            },
            {
              "file": "2-join.png",
              "caption": "Joining a secured network that is not saved asks for its password"
            },
            {
              "file": "3-actions.png",
              "caption": "A saved network: join it, copy its name or its password, forget it"
            },
            {
              "file": "4-forget.png",
              "caption": "Forget asks first, since the saved password goes with it"
            },
            {
              "file": "5-detail.png",
              "caption": "The current network's detail (cmd+I): connected and its security as chips, signal and channel large, then its address"
            }
          ],
          "actions": [
            {
              "title": "Join",
              "description": "A saved or open network joins at once; a secured new one takes its password in the bar, or asks in a form.",
              "keys": "enter"
            },
            {
              "title": "Copy password",
              "description": "The saved password; the macOS keychain prompts.",
              "keys": "cmd+shift+c"
            },
            {
              "title": "Copy IP",
              "description": "On the current row.",
              "keys": "cmd+c"
            },
            {
              "title": "Copy name",
              "description": "On a known or available row.",
              "keys": "cmd+c"
            },
            {
              "title": "Forget",
              "description": "Removes the saved network, after a confirm; several marked networks at once.",
              "keys": "ctrl+x"
            },
            {
              "title": "Scan",
              "description": "On the Scan for Networks row: a fresh scan, then the list again.",
              "keys": "enter"
            },
            {
              "title": "Turn off / Turn on",
              "description": "On the Wi-Fi row: the radio.",
              "keys": "enter"
            },
            {
              "title": "Open System Settings",
              "description": "On the Location row (macOS, access refused): the Location Services pane.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "wifi": {
            "title": "Wi-Fi",
            "kind": "live",
            "description": "Current, known and available networks with their signal.",
            "keys": [
              {
                "keys": "enter",
                "title": "Join, scan, or turn the radio off or on"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the IP or the network's name"
              },
              {
                "keys": "cmd+shift+c",
                "title": "Copy the password"
              },
              {
                "keys": "ctrl+x",
                "title": "Forget"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/wifi",
      "tagline": "Join, forget or inspect Wi-Fi networks; switch the radio",
      "category": "system",
      "screenshots": [
        "https://pal.cagdas.io/extensions/wifi/screenshots/1-networks-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/1-networks.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/2-join-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/2-join.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/4-forget-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/4-forget.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/5-detail-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/5-detail.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/wifi/screenshots/1-networks.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/2-join.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/4-forget.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/5-detail.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/wifi/screenshots/1-networks-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/2-join-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/4-forget-dark.png",
        "https://pal.cagdas.io/extensions/wifi/screenshots/5-detail-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "window-management",
      "kind": "bundled",
      "title": "Window Management",
      "description": "Move and resize the focused window, or any window, from the keyboard: halves, thirds, quarters, maximize, center, resize to a size, nudge, fullscreen, the next display, and back to where it was.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󱂪",
          "bg": "indigo"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/window-management@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/window-management",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "window-management",
        "title": "Window Management",
        "description": "Move and resize the focused window, or any window, from the keyboard: halves, thirds, quarters, maximize, center, resize to a size, nudge, fullscreen, the next display, and back to where it was.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󱂪",
            "bg": "indigo"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "number",
            "id": "gap",
            "label": "Gap",
            "description": "Pixels between a window and the screen edge, and between two windows of a split.",
            "min": 0,
            "max": 128,
            "step": 1,
            "unit": "px",
            "default": 0
          },
          {
            "kind": "number",
            "id": "almost_maximize_percent",
            "label": "Almost Maximize",
            "description": "How much of the screen Almost Maximize fills, centred.",
            "min": 10,
            "max": 100,
            "step": 1,
            "unit": "%",
            "default": 90
          },
          {
            "kind": "number",
            "id": "reasonable_size_percent",
            "label": "Reasonable Size",
            "description": "How much of the screen Reasonable Size fills, centred.",
            "min": 10,
            "max": 100,
            "step": 1,
            "unit": "%",
            "default": 60
          },
          {
            "kind": "number",
            "id": "step",
            "label": "Move step",
            "description": "Pixels Move Left, Right, Up and Down nudge the window by.",
            "min": 1,
            "max": 512,
            "step": 1,
            "unit": "px",
            "default": 32
          },
          {
            "kind": "boolean",
            "id": "cycle",
            "label": "Cycle on repeat",
            "text": "A half applied again steps to two thirds, then a third, then the half (left and right families), as Rectangle does",
            "default": false
          }
        ],
        "store": {
          "tagline": "Snap, resize and move any window from the keyboard",
          "category": "productivity",
          "features": [
            "32 layouts: halves, thirds, quarters, maximize, center, larger, smaller, move, next display, fullscreen, minimize",
            "Acts on the window you were in; `cmd+enter` picks another window first",
            "Restore puts a window back where it was before a run of layouts",
            "Resize to a size typed in the search bar (`1280x720`), keeping the window centred",
            "A gap between windows and a nudge step to set; with `cycle` on, Left Half again steps through two thirds and a third",
            "Global hotkeys per layout move the focused window without opening the panel"
          ],
          "permissions": [
            "accessibility"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-layouts.png",
              "caption": "Every layout with its diagram; Enter applies it to the focused window"
            },
            {
              "file": "2-search.png",
              "caption": "Typing narrows the list: quarter leaves the four corners"
            },
            {
              "file": "3-arrange.png",
              "caption": "Arrange Window picks the window first, from every one open, then the layout for it"
            },
            {
              "file": "4-target.png",
              "caption": "The layouts again, the picked window named under each"
            },
            {
              "file": "5-verbs.png",
              "caption": "Moves by a step, the next display, fullscreen, minimize, unminimize and restore, each with its diagram"
            },
            {
              "file": "6-resize.png",
              "caption": "Resize to… is a form: a size in pixels and, if you like, a place; left blank the window stays centred where it is"
            }
          ],
          "actions": [
            {
              "title": "Apply",
              "description": "The layout on the focused window.",
              "keys": "enter"
            },
            {
              "title": "Apply to…",
              "description": "Pick a window from the open ones, then the layout goes on that one.",
              "keys": "cmd+enter"
            },
            {
              "title": "Resize",
              "description": "On Resize to…: the bar takes the size (required) and X, Y (optional); the size (and place) typed goes on the window and the HUD says the size.",
              "keys": "enter"
            },
            {
              "title": "Arrange",
              "description": "In Arrange Window: the layouts for the picked window.",
              "keys": "enter"
            }
          ]
        },
        "links": {
          "layout": {
            "description": "Move the focused window to a layout",
            "params": {
              "name": {
                "description": "left_half, right_half, maximize, larger, move_left, fullscreen, minimize, next_display, restore, ... (the row ids; Resize to… takes its size in the bar, not from a link)",
                "required": true
              }
            }
          }
        },
        "palettes": {
          "window-management": {
            "title": "Window Management",
            "kind": "list",
            "description": "One row per layout; Enter applies it to the window you were in.",
            "keys": [
              {
                "keys": "enter",
                "title": "Apply to the focused window"
              },
              {
                "keys": "cmd+enter",
                "title": "Apply to a window you pick"
              }
            ]
          },
          "arrange": {
            "title": "Arrange Window",
            "kind": "input",
            "description": "Pick a window first, then the layout.",
            "keys": [
              {
                "keys": "enter",
                "title": "Pick the window, then its layout"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/window-management",
      "tagline": "Snap, resize and move any window from the keyboard",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/window-management/screenshots/1-layouts-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/1-layouts.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/3-arrange-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/3-arrange.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/4-target-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/4-target.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/5-verbs-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/5-verbs.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/6-resize-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/6-resize.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/window-management/screenshots/1-layouts.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/2-search.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/3-arrange.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/4-target.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/5-verbs.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/6-resize.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/window-management/screenshots/1-layouts-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/2-search-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/3-arrange-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/4-target-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/5-verbs-dark.png",
        "https://pal.cagdas.io/extensions/window-management/screenshots/6-resize-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": true,
      "links": [
        {
          "route": "layout",
          "url": "pal://window-management/layout?name=\u003cname\u003e",
          "cli": "pal call window-management/layout name=\u003cname\u003e",
          "description": "Move the focused window to a layout",
          "params": [
            {
              "name": "name",
              "description": "left_half, right_half, maximize, larger, move_left, fullscreen, minimize, next_display, restore, ... (the row ids; Resize to… takes its size in the bar, not from a link)",
              "required": true
            }
          ]
        }
      ],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "windows",
      "kind": "bundled",
      "title": "Windows",
      "description": "Every open window with its app's icon, most recently used first and grouped by app: `enter` switches to it, and you can close, minimise or hide from the keyboard. Spaces and workspaces are listed too, each with the apps on it.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󱂬",
          "bg": "slate"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/windows@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/windows",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "windows",
        "title": "Windows",
        "description": "Every open window with its app's icon, most recently used first and grouped by app: `enter` switches to it, and you can close, minimise or hide from the keyboard. Spaces and workspaces are listed too, each with the apps on it.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󱂬",
            "bg": "slate"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "include_minimized",
            "label": "Minimised windows",
            "text": "List minimised windows too",
            "description": "Focusing a minimised window restores it.",
            "default": true
          },
          {
            "kind": "list",
            "id": "spaces",
            "label": "Space names",
            "description": "Names for the desktops by number: the first entry names Desktop 1. A named space's row is titled by it, the windows rows say `space \u003cname\u003e`, and its row id is the name, so `[palettes.windows-spaces.item_hotkeys]` reads `term = \"ctrl+alt+shift+a\"`.",
            "placeholder": "web",
            "default": []
          },
          {
            "kind": "boolean",
            "id": "back_and_forth",
            "label": "Back and forth",
            "text": "A space's hotkey pressed while on it goes to the previous space",
            "description": "Hyprland's workspace_back_and_forth: the same key toggles between a space and where you came from. Enter on the current space's row does the same.",
            "default": false
          },
          {
            "kind": "list",
            "id": "toggle",
            "label": "Toggle pair",
            "description": "Two space names (or numbers) the Toggle row flips between: on the first it goes to the second, anywhere else to the first. toggle = \"ctrl+f\" under item_hotkeys makes it a key.",
            "placeholder": "web",
            "default": []
          }
        ],
        "store": {
          "tagline": "Switch to any open window or space, most recently used first",
          "category": "productivity",
          "features": [
            "Every window, most recently used first, grouped by app; window titles are found at the root",
            "Tags for hidden, minimised and on another space, and the monitor when known",
            "`cmd+w` closes, `cmd+m` minimises, `cmd+h` hides the app; Close all and Minimize all act on every window of an app",
            "Spaces: a row per Space or workspace with its apps; `enter` switches, Previous space goes back",
            "Named desktops can take global hotkeys",
            "macOS, and Hyprland, Sway and X11 on Linux, detected by itself"
          ],
          "permissions": [
            "accessibility",
            "automation"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-list.png",
              "caption": "Every open window in a section per app, the other display and a minimised one marked"
            },
            {
              "file": "2-actions.png",
              "caption": "Focus, close, minimise or hide the app, or minimise and close all of its windows at once"
            },
            {
              "file": "3-root.png",
              "caption": "Windows are root results: chrome finds its three windows and the space it is on"
            },
            {
              "file": "4-confirm.png",
              "caption": "Closing every window of an app asks first"
            },
            {
              "file": "5-spaces.png",
              "caption": "Spaces: each desktop by name with the apps on it, the current and the previous one tagged"
            }
          ],
          "actions": [
            {
              "title": "Focus",
              "description": "Hides the panel, then raises the window, restoring it if minimised.",
              "keys": "enter"
            },
            {
              "title": "Close",
              "description": "The palette stays open and lists again.",
              "keys": "cmd+w"
            },
            {
              "title": "Minimize",
              "description": "Not offered on a window that already is.",
              "keys": "cmd+m"
            },
            {
              "title": "Hide app",
              "description": "macOS: hides the window's process through System Events; marked windows hide their apps at once. Not offered on a hidden app.",
              "keys": "cmd+h"
            },
            {
              "title": "Show app",
              "description": "macOS, on a hidden app's window: the app comes forward with every window it had; the panel hides.",
              "keys": "cmd+shift+h"
            },
            {
              "title": "Minimize all of this app",
              "description": "On an app with more than one window.",
              "keys": "cmd+shift+m"
            },
            {
              "title": "Close all of this app",
              "description": "Asks first.",
              "keys": "cmd+shift+w"
            },
            {
              "title": "Go",
              "description": "Spaces: hides the panel, then brings the space in front. On the current space with Back and forth on, goes to the previous one.",
              "keys": "enter"
            }
          ]
        },
        "palettes": {
          "windows": {
            "title": "Windows",
            "tier": "primary",
            "kind": "live",
            "remember": false,
            "description": "What is open right now, most recently used first.",
            "hold": "alt+tab",
            "tap": true,
            "keys": [
              {
                "keys": "enter",
                "title": "Focus the window"
              },
              {
                "keys": "cmd+w",
                "title": "Close it"
              },
              {
                "keys": "cmd+m",
                "title": "Minimize it"
              },
              {
                "keys": "cmd+h",
                "title": "Hide the app"
              },
              {
                "keys": "cmd+shift+h",
                "title": "Show a hidden app"
              },
              {
                "keys": "cmd+shift+m",
                "title": "Minimize all of the app's windows"
              },
              {
                "keys": "cmd+shift+w",
                "title": "Close all of the app's windows, after a confirm"
              }
            ]
          },
          "spaces": {
            "title": "Spaces",
            "kind": "live",
            "remember": false,
            "description": "Every Space, workspace or desktop in the desktop's order, with the apps on it; Enter brings it in front. Previous space goes back to the one left most recently; Toggle flips between the two spaces named in the setting.",
            "keys": [
              {
                "keys": "enter",
                "title": "Bring the space in front"
              }
            ]
          }
        },
        "keywords": [
          "window",
          "switcher",
          "space",
          "desktop",
          "workspace"
        ]
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/windows",
      "tagline": "Switch to any open window or space, most recently used first",
      "category": "productivity",
      "screenshots": [
        "https://pal.cagdas.io/extensions/windows/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/4-confirm-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/4-confirm.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/5-spaces-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/5-spaces.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/windows/screenshots/1-list.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/2-actions.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/3-root.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/4-confirm.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/5-spaces.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/windows/screenshots/1-list-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/2-actions-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/3-root-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/4-confirm-dark.png",
        "https://pal.cagdas.io/extensions/windows/screenshots/5-spaces-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "wordle",
      "kind": "registry",
      "title": "Wordle",
      "description": "The five-letter word game in the panel, keyboard only: a daily puzzle, the same everywhere, and practice words once it is done. Your streak and stats are kept, and follow you to every machine you sign in on.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M1.5 1.5h3.5v3.5H1.5zM6.25 1.5h3.5v3.5h-3.5zM11 1.5h3.5v3.5H11zM1.5 6.25h3.5v3.5H1.5zM6.25 6.25h3.5v3.5h-3.5zM11 6.25h3.5v3.5H11zM1.5 11h3.5v3.5H1.5zM6.25 11h3.5v3.5h-3.5zM11 11h3.5v3.5H11z",
          "bg": "green"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/wordle@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/wordle",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "wordle",
        "title": "Wordle",
        "description": "The five-letter word game in the panel, keyboard only: a daily puzzle, the same everywhere, and practice words once it is done. Your streak and stats are kept, and follow you to every machine you sign in on.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M1.5 1.5h3.5v3.5H1.5zM6.25 1.5h3.5v3.5h-3.5zM11 1.5h3.5v3.5H11zM1.5 6.25h3.5v3.5H1.5zM6.25 6.25h3.5v3.5h-3.5zM11 6.25h3.5v3.5H11zM1.5 11h3.5v3.5H1.5zM6.25 11h3.5v3.5h-3.5zM11 11h3.5v3.5H11z",
            "bg": "green"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "boolean",
            "id": "daily",
            "label": "Daily puzzle",
            "text": "One puzzle a day from the date",
            "description": "Opening the palette on a new day starts that day's word, the same on every machine. Off, every game is a random word.",
            "default": true
          },
          {
            "kind": "boolean",
            "id": "hard_mode",
            "label": "Hard mode",
            "text": "Revealed hints must be used",
            "description": "A guess must keep every green letter in place and use every amber one. Applies from the next game.",
            "default": false
          }
        ],
        "sync": {
          "game": "latest",
          "stats": {
            "fields": {
              "played": "sum",
              "won": "sum",
              "best": "max",
              "dist": {
                "fields": {
                  "1": "sum",
                  "2": "sum",
                  "3": "sum",
                  "4": "sum",
                  "5": "sum",
                  "6": "sum"
                }
              }
            }
          },
          "daily_won": "union",
          "daily_lost": "union"
        },
        "leaderboards": [
          {
            "id": "daily/*",
            "title": "Wordle #{1}",
            "order": "asc",
            "format": "moves",
            "min": 1,
            "max": 6
          },
          {
            "id": "streak",
            "title": "Longest streak",
            "order": "desc",
            "format": "points",
            "min": 1,
            "max": 100000
          }
        ],
        "store": {
          "tagline": "Wordle in the panel: a daily puzzle, practice words, stats",
          "category": "fun",
          "features": [
            "Type a guess and press `enter`; the tiles flip green, amber or grey and the keyboard colours as you go",
            "A daily puzzle from the date, the same on every machine; `n` for practice words once it is done",
            "Hard mode keeps greens in place and makes ambers count; an unknown word is flagged over the board",
            "Stats: played, win %, streak and the guess distribution; `c` copies the emoji grid to share",
            "Leave any time and come back to the same game, even after a restart",
            "The word lists ship with it; nothing is fetched",
            "Each daily's guesses go on that puzzle's leaderboard, your longest streak on another; signed in to a pal account, the game, the stats and the streak follow you to every machine"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-game.png",
              "caption": "The daily, three guesses in and two letters typed: the keyboard shows what the guesses found"
            },
            {
              "file": "2-notice.png",
              "caption": "A word that is not in the list: a notice under the title, and the row stays for editing"
            },
            {
              "file": "3-solved.png",
              "caption": "Solved in four: the praise, the stats and the guess distribution, C copies the grid",
              "cover": [
                180,
                231,
                690,
                338
              ]
            }
          ],
          "actions": [
            {
              "title": "Type a letter",
              "description": "Any letter key fills the current row.",
              "keys": "a"
            },
            {
              "title": "Submit the guess",
              "description": "Five letters that make a word in the list.",
              "keys": "enter"
            },
            {
              "title": "Delete a letter",
              "description": "Backspace takes the last letter back.",
              "keys": "backspace"
            },
            {
              "title": "Copy the result",
              "description": "The emoji grid with the puzzle number and the score, once the game is over.",
              "keys": "c"
            },
            {
              "title": "Today's puzzle / Practice game",
              "description": "New game: today's puzzle if it is unplayed, else a practice word. `n` once the game is over, `cmd+n` while a practice game is on.",
              "keys": "n, cmd+n"
            },
            {
              "title": "Sign in",
              "description": "After a daily while signed out: opens Settings › Account, so your scores are kept with your account.",
              "keys": "s"
            }
          ]
        },
        "palettes": {
          "wordle": {
            "title": "Wordle",
            "kind": "view",
            "description": "The board. Escape leaves mid-game; the game is there when you come back.",
            "keys": [
              {
                "keys": "a",
                "title": "Type a letter"
              },
              {
                "keys": "enter",
                "title": "Submit the guess"
              },
              {
                "keys": "backspace",
                "title": "Delete a letter"
              },
              {
                "keys": "c",
                "title": "Copy the result, once the game is over"
              },
              {
                "keys": "n",
                "title": "New game, once the game is over"
              },
              {
                "keys": "cmd+n",
                "title": "New game mid-game, when a practice word can be dropped"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/wordle",
      "tagline": "Wordle in the panel: a daily puzzle, practice words, stats",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/wordle/screenshots/1-game-dark.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/1-game.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/2-notice-dark.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/2-notice.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/3-solved-dark.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/3-solved.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/wordle/screenshots/1-game.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/2-notice.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/3-solved.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/wordle/screenshots/1-game-dark.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/2-notice-dark.png",
        "https://pal.cagdas.io/extensions/wordle/screenshots/3-solved-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "yahtzee",
      "kind": "registry",
      "title": "Yahtzee",
      "description": "Solo Yahtzee: five dice, three rolls a round, thirteen rounds, with the card showing what every category would score. Play with the mouse or one-handed on the arrow keys; your game in progress, best score and average are kept.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "glyph": "󰇎",
          "bg": "amber"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/yahtzee@v0.17.4",
      "source": "https://github.com/zcag/pal-games/tree/HEAD/yahtzee",
      "commit": "16c5a9dde3d14b8761ba1bb6e500b65c262aeda6",
      "manifest": {
        "name": "yahtzee",
        "title": "Yahtzee",
        "description": "Solo Yahtzee: five dice, three rolls a round, thirteen rounds, with the card showing what every category would score. Play with the mouse or one-handed on the arrow keys; your game in progress, best score and average are kept.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "glyph": "󰇎",
            "bg": "amber"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "sync": {
          "state": "local",
          "record": {
            "fields": {
              "games": "sum",
              "sum": "sum",
              "best": "max"
            }
          }
        },
        "leaderboards": [
          {
            "id": "daily",
            "title": "Daily dice",
            "order": "desc",
            "format": "points",
            "period": "day",
            "min": 0,
            "max": 1575
          },
          {
            "id": "high",
            "title": "High score",
            "order": "desc",
            "format": "points",
            "min": 0,
            "max": 1575
          }
        ],
        "store": {
          "tagline": "Solo Yahtzee with the scores in plain sight, by mouse or keys",
          "category": "fun",
          "features": [
            "The scorecard shows what each open category would score with the dice as they lie",
            "One-handed: the arrows pick and hold dice, `space` rolls, `↓` jumps to the best category, `enter` scores",
            "The upper bonus as a bar toward 63, greyed once it is out of reach",
            "Hasbro's rules in full, including Yahtzee bonuses and the Joker rules",
            "Dice that tumble, confetti for a Yahtzee, and the final score beside your best and average",
            "Leave any time and pick the game up again, even after a restart",
            "Daily dice, the same rolls for everyone that day (`Y`); signed in to pal, your record follows you, and finished cards go on leaderboards: the day's best and the all-time high"
          ],
          "permissions": [],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-roll.png",
              "caption": "Mid-round: three fours kept, each open box showing what it would score",
              "cover": [
                332,
                196,
                787,
                386
              ]
            },
            {
              "file": "2-choose.png",
              "caption": "Out of throws: the cursor on the card, the dice it counts ringed, the total showing what it adds"
            },
            {
              "file": "3-yahtzee.png",
              "caption": "A second Yahtzee: 100 more, and as a Joker it fills a straight"
            },
            {
              "file": "4-over.png",
              "caption": "Game over: the final score with the best and the average"
            }
          ],
          "actions": [
            {
              "title": "Roll",
              "description": "Up to three times a round; held dice stay.",
              "keys": "space, up, r"
            },
            {
              "title": "Hold a die",
              "description": "Enter on the die under the cursor, or its number.",
              "keys": "enter, 1-5"
            },
            {
              "title": "Score a category",
              "description": "cmd+k lists the ones the dice may go in, the one that adds most first.",
              "keys": "enter"
            },
            {
              "title": "New game",
              "description": "Asks first mid-game; the record is kept.",
              "keys": "n"
            },
            {
              "title": "Daily dice",
              "description": "A fresh card on the day's dice: the same rolls for everyone until midnight UTC, whatever you hold. A finished card goes on the day's board. Asks first mid-game.",
              "keys": "y"
            }
          ],
          "play": true
        },
        "palettes": {
          "yahtzee": {
            "title": "Yahtzee",
            "kind": "view",
            "description": "The dice and the card. Escape leaves mid-game; it is there when you come back.",
            "keys": [
              {
                "keys": "space",
                "title": "Roll (also r; up on the dice)"
              },
              {
                "keys": "left",
                "title": "The die to the left (right, the one to the right); on the card, the other column"
              },
              {
                "keys": "enter",
                "title": "Hold or release the die; on the card, score the category; the first roll of a round"
              },
              {
                "keys": "1",
                "title": "Hold or release die 1 (2 to 5 likewise)"
              },
              {
                "keys": "down",
                "title": "To the card, on the category that adds most; then the next one down"
              },
              {
                "keys": "up",
                "title": "The category above; past the top, back to the dice; on the dice, roll"
              },
              {
                "keys": "n",
                "title": "New game, after a confirm mid-game"
              },
              {
                "keys": "y",
                "title": "The daily dice, asking first mid-game"
              }
            ]
          }
        }
      },
      "playable": true,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/yahtzee",
      "tagline": "Solo Yahtzee with the scores in plain sight, by mouse or keys",
      "category": "fun",
      "screenshots": [
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/1-roll-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/1-roll.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/2-choose-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/2-choose.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/3-yahtzee-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/3-yahtzee.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/4-over-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/4-over.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/1-roll.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/2-choose.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/3-yahtzee.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/4-over.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/1-roll-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/2-choose-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/3-yahtzee-dark.png",
        "https://pal.cagdas.io/extensions/yahtzee/screenshots/4-over-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    },
    {
      "name": "youtube",
      "kind": "registry",
      "title": "YouTube",
      "description": "Search YouTube from the panel, with thumbnails, channels, lengths and views, and trending when nothing is typed. Open a video in the browser, play it in IINA, mpv or VLC, or save it to Watch Later; works with a free API key or an Invidious instance.",
      "version": "0.1.0",
      "icon": {
        "tile": {
          "svg": "M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z",
          "box": 24,
          "bg": "#FF0000"
        }
      },
      "author": "pal",
      "spec": "github:zcag/pal/extensions/youtube@v0.17.4",
      "source": "https://github.com/zcag/pal-extensions/tree/HEAD/youtube",
      "commit": "4d2559cf9c04d0133c97d7c897f19a14acb9eace",
      "manifest": {
        "name": "youtube",
        "title": "YouTube",
        "description": "Search YouTube from the panel, with thumbnails, channels, lengths and views, and trending when nothing is typed. Open a video in the browser, play it in IINA, mpv or VLC, or save it to Watch Later; works with a free API key or an Invidious instance.",
        "version": "0.1.0",
        "icon": {
          "tile": {
            "svg": "M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z",
            "box": 24,
            "bg": "#FF0000"
          }
        },
        "author": "pal",
        "repo": "bundled",
        "license": "MIT",
        "settings": [
          {
            "kind": "secret",
            "id": "api_key",
            "required": true,
            "only": {
              "invidious_url": ""
            },
            "label": "Data API key",
            "description": "A Google Cloud API key with YouTube Data API v3 enabled on its project (console.cloud.google.com › APIs \u0026 Services › Enable APIs › YouTube Data API v3 › Credentials). Free; the daily quota of 10,000 units is about 100 searches. Wins over the Invidious instance when both are set.",
            "placeholder": "AIza…",
            "default": ""
          },
          {
            "kind": "text",
            "id": "invidious_url",
            "label": "Invidious instance",
            "description": "Searched without a key through `/api/v1`. Most public instances have turned the API off (only invidious.f5.si answered on 2026-09-17); a self-hosted one is the reliable choice.",
            "placeholder": "https://invidious.example.org",
            "default": ""
          },
          {
            "kind": "select",
            "id": "player",
            "label": "Player",
            "description": "What cmd+Enter plays the video in. Auto takes IINA, then mpv, then VLC, whichever is installed, else the browser. mpv and VLC need yt-dlp for YouTube.",
            "options": [
              {
                "id": "auto",
                "title": "Auto (IINA, mpv, VLC, else the browser)"
              },
              {
                "id": "iina",
                "title": "IINA"
              },
              {
                "id": "mpv",
                "title": "mpv"
              },
              {
                "id": "vlc",
                "title": "VLC"
              },
              {
                "id": "browser",
                "title": "The browser"
              }
            ],
            "default": "auto"
          },
          {
            "kind": "text",
            "id": "region",
            "label": "Region",
            "description": "A two-letter country code for the trending list; empty is YouTube's default.",
            "placeholder": "TR",
            "default": ""
          }
        ],
        "store": {
          "tagline": "Search YouTube, then open, play or save for later",
          "category": "media",
          "features": [
            "Videos with thumbnail, channel, length, views and age; trending while nothing is typed",
            "`enter` opens in the browser, `cmd+enter` plays in IINA, mpv or VLC, `cmd+c` copies the link",
            "Watch Later (`cmd+s`), its videos found by title at the root",
            "Channels by name, with their latest videos",
            "A free YouTube Data API key, or an Invidious instance without one",
            "`yt: lofi` at the root answers inline"
          ],
          "permissions": [
            "network"
          ],
          "platforms": [
            "macos",
            "linux"
          ],
          "screenshots": [
            {
              "file": "1-search.png",
              "caption": "A search for lofi: each video with its channel, length, views and age, and the detail pane with the thumbnail"
            },
            {
              "file": "2-trending.png",
              "caption": "With nothing typed, the videos trending in your region"
            },
            {
              "file": "3-actions.png",
              "caption": "Open it, play it in your own player, copy the link, keep it for later or go to the channel"
            },
            {
              "file": "4-channels.png",
              "caption": "Channels by name, each with its avatar and what it is about; Enter lists a channel's latest videos"
            },
            {
              "file": "5-later.png",
              "caption": "Watch Later: the videos cmd+S kept, on this Mac and no account needed"
            },
            {
              "file": "6-no-key.png",
              "caption": "Before it is set up: the one setting to fill, a free API key or an Invidious instance"
            }
          ],
          "actions": [
            {
              "title": "Open in browser",
              "keys": "enter"
            },
            {
              "title": "Play in player",
              "description": "IINA, mpv or VLC per the `player` setting; the browser when none is installed.",
              "keys": "cmd+enter"
            },
            {
              "title": "Copy URL",
              "keys": "cmd+c"
            },
            {
              "title": "Watch later",
              "keys": "cmd+s"
            },
            {
              "title": "Open the channel",
              "keys": "cmd+shift+o"
            },
            {
              "title": "Latest videos",
              "description": "On a channel row: its videos, newest first.",
              "keys": "enter"
            },
            {
              "title": "Remove from Watch Later",
              "keys": "cmd+d"
            }
          ]
        },
        "palettes": {
          "search": {
            "title": "YouTube",
            "kind": "input",
            "inline": true,
            "match": "^\\s*yt\\s*:\\s*\\S",
            "fallback": "Search YouTube for “{query}”",
            "description": "Type to search videos; nothing typed lists what is trending. `yt:` at the root answers inline.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+enter",
                "title": "Play in IINA, mpv or VLC"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the url"
              },
              {
                "keys": "cmd+s",
                "title": "Watch later"
              },
              {
                "keys": "cmd+shift+o",
                "title": "Open the channel"
              }
            ]
          },
          "channels": {
            "title": "YouTube Channels",
            "kind": "input",
            "description": "Channels by name; Enter lists the channel's latest videos. Subscriptions need OAuth and are not listed.",
            "keys": [
              {
                "keys": "enter",
                "title": "Latest videos"
              },
              {
                "keys": "cmd+enter",
                "title": "Open the channel"
              },
              {
                "keys": "cmd+c",
                "title": "Copy the url"
              }
            ]
          },
          "later": {
            "title": "Watch Later",
            "kind": "live",
            "remember": false,
            "description": "Videos kept with cmd+s, newest first; the same actions, and cmd+d removes one.",
            "keys": [
              {
                "keys": "enter",
                "title": "Open in the browser"
              },
              {
                "keys": "cmd+enter",
                "title": "Play in the player"
              },
              {
                "keys": "cmd+d",
                "title": "Remove"
              }
            ]
          }
        }
      },
      "playable": false,
      "updated_at": "2026-11-02T03:38:11Z",
      "url": "https://pal.cagdas.io/extensions/youtube",
      "tagline": "Search YouTube, then open, play or save for later",
      "category": "media",
      "screenshots": [
        "https://pal.cagdas.io/extensions/youtube/screenshots/1-search-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/1-search.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/2-trending-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/2-trending.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/4-channels-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/4-channels.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/5-later-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/5-later.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/6-no-key-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/6-no-key.png"
      ],
      "panel_screenshots": [
        "https://pal.cagdas.io/extensions/youtube/screenshots/1-search.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/2-trending.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/3-actions.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/4-channels.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/5-later.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/6-no-key.png"
      ],
      "bar_screenshots": [],
      "panel_screenshots_dark": [
        "https://pal.cagdas.io/extensions/youtube/screenshots/1-search-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/2-trending-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/3-actions-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/4-channels-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/5-later-dark.png",
        "https://pal.cagdas.io/extensions/youtube/screenshots/6-no-key-dark.png"
      ],
      "bar_screenshots_dark": [],
      "has_bar": false,
      "bar_items": [],
      "has_links": false,
      "links": [],
      "multi": false,
      "has_readme": true
    }
  ],
  "synced_at": "2026-11-02T03:38:11Z"
}
