{"id":"sayr","repo":"dorasto/sayr","url":"https://github.com/dorasto/sayr/tree/main/packages/paseo-plugin","name":"sayr","description":"A paseo plugin for viewing and managing your Sayr tasks","categories":["productivity"],"platforms":[],"caveats":["Requires an account on Sayr.io","Requires the Sayr CLI to be authenticated"],"images":["https://raw.githubusercontent.com/dorasto/sayr/8710e7df54b0ac2765974373c8ca96b4c068ab24/packages/paseo-plugin/assets/sayr-plguin-1.png","https://raw.githubusercontent.com/dorasto/sayr/8710e7df54b0ac2765974373c8ca96b4c068ab24/packages/paseo-plugin/assets/paseo-plugin-2.png","https://raw.githubusercontent.com/dorasto/sayr/8710e7df54b0ac2765974373c8ca96b4c068ab24/packages/paseo-plugin/assets/sayr.png"],"health":{"manifestValid":true,"hasReadme":true,"hasLicense":true,"hasTests":false,"hasTypecheckScript":true,"updatedRecently":true},"scannedAt":"2026-09-14T08:29:11.089Z","addedAt":"2026-09-13T06:40:48+01:00","path":"packages/paseo-plugin","version":"0.1.0","security":{"status":"passed","blockingFindings":0,"advisoryFindings":0,"scannedAt":"2026-09-14T08:27:38.731Z","commit":"8710e7df54b0ac2765974373c8ca96b4c068ab24"},"author":"Tom Lundy","license":"NOASSERTION","paseoVersionRequirement":">=0.8.0","manifest":{"id":"sayr","requirements":{"paseo":">=0.8.0"}},"repoMeta":{"stars":23,"defaultBranch":"main","pushedAt":"2026-09-13T14:47:13Z"},"owner":{"login":"dorasto","avatarUrl":"https://avatars.githubusercontent.com/u/150166682?v=4"},"installNotesHtml":"<pre><code class=\"language-bash\">paseo plugin add dorasto/sayr --ref main --path packages/paseo-plugin\n</code></pre>\n<p>Then work through <a href=\"#requirements\">Requirements</a> below — the plugin is a thin shell over the <code>sayr</code>\nCLI, so it can't do anything until that's installed and logged in on the daemon machine.</p>","readmeText":"# Sayr in Paseo\n\nProject management right from your coding agent. View, comment, and manage your Sayr tasks, or click a button and pass it off to an agent. Define a default prompt when passing it along, or customize it when passing off.\n\n## Screenshots\n\n<table>\n<tr>\n<td width=\"33%\" valign=\"top\">\n\n**Board** — multi-org, status columns, filters\n\n<img src=\"assets/sayr-plguin-1.png\" alt=\"Sayr plugin board view\">\n\n</td>\n<td width=\"33%\" valign=\"top\">\n\n**Task detail** — inline editing, rich rendering, AI summary\n\n<img src=\"assets/paseo-plugin-2.png\" alt=\"Sayr plugin task detail sheet\">\n\n</td>\n<td width=\"33%\" valign=\"top\">\n\n**For reference** — the real Sayr web app the plugin's board mirrors\n\n<img src=\"assets/sayr.png\" alt=\"Sayr web app board view\">\n\n</td>\n</tr>\n</table>\n\n## Requires\n\n- An account on [Sayr.io](https://sayr.io) or,\n- A self hosted instance of Sayr\n- Valid API key (can be created [here](https://admin.sayr.io/settings/api-keys))\n- [Sayr CLI](https://sayr.io/docs/cli)\n\n## Install\n\n```bash\npaseo plugin add dorasto/sayr --ref main --path packages/paseo-plugin\n```\n\nThen work through [Requirements](#requirements) below — the plugin is a thin shell over the `sayr`\nCLI, so it can't do anything until that's installed and logged in on the daemon machine.\n\n## How it works\n\nThe plugin doesn't call the Sayr API directly. Every RPC handler shells out to an installed `sayr`\nCLI binary (`@sayrio/cli`, see [`packages/cli/README.md`](../cli/README.md)) on the daemon machine and\nparses its `--json` output. That means:\n\n- Auth is whatever `sayr login` already has stored in `~/.sayr/config.json` on the daemon — the\n  plugin never sees or stores a token itself.\n- Every write action (status, priority, assignees, comments) round-trips through the same CLI\n  commands you could run by hand, so plugin and CLI can never drift in what they're capable of.\n\n## Requirements\n\n- Paseo `>=0.8.0`.\n- The `sayr` CLI installed and logged in on the **daemon** machine (not just wherever the Paseo app\n  itself is running):\n  ```bash\n  npm install -g @sayrio/cli\n  sayr login --token api_xxxxxxxx\n  ```\n\n## Settings\n\n**Settings → Plugins → Sayr** lets you point the plugin at a different installed binary — e.g.\n`sayr-local` to work against a local dev backend instead of production (see the CLI README's\n`SAYR_PROFILE` section). Stored server-side at `$PASEO_HOME/plugins/sayr/settings.json`, defaulting\nto `sayr`.\n\n## Features\n\n- **Board** — every organization the CLI's logged-in user belongs to, fetched in parallel, with\n  backlog/todo/in-progress columns (done/canceled tasks aren't fetched at all — the board isn't a\n  full archive). Search, and per-org/per-priority filter chips.\n- **Task detail** — opens as a resizable side sheet, not a modal, mirroring the real product's\n  panel behavior rather than replacing the whole screen. Status, priority, and assignees are all\n  editable inline; assignee/category names and colors resolve the same way the web app's own\n  pickers do.\n- **Rich comment/description rendering** — task descriptions and comment bodies are ProseKit\n  documents, not markdown strings. `client/prosekit-view.tsx` renders the real node/mark tree\n  (headings, bold/italic/strike/underline/code, lists, blockquotes, code blocks) as actual styled\n  React Native elements, plus `@user`/`#task`/`!category` mention pills — not a flattened,\n  unformatted dump of the text. See that file's header comment for exactly what is and isn't\n  covered (no live task-title lookup in task mentions, no avatar image inside a mention pill, no\n  table grids, no code block syntax highlighting).\n- **Send to agent** — hands a task's title, status, priority, description, and recent comments off\n  to a new Paseo agent as a seed prompt (`client/agent-prompt.ts`), via a real workspace + agent\n  creation call, not just a copy-paste.\n\n## Architecture\n\nStandard Paseo plugin layout — `client/` (React Native, no Node/DOM APIs except the one\nplatform-gated `client/web.ts`), `server/` (the daemon subprocess, shells out to the CLI, can use\nNode freely), `shared/` (Zod RPC contracts and plain types, importable from both). Every write and\nevery non-trivial read goes through a `defineRpc` contract in `shared/task.ts`/`shared/settings.ts`,\nhandled in `server/task-handlers.ts`/`server/settings-handlers.ts`, called from `client/` via\n`useRpc()`. See `AGENTS.md`'s row for this package and the individual file header comments for the\nreasoning behind specific choices (why the sheet isn't a host `Modal`, why colors are priority-based\nrather than per-org, why `shared/` has small local copies of a couple of `@repo/util` helpers instead\nof importing them, etc.).\n\n## Development\n\n```bash\ncd packages/paseo-plugin\npnpm typecheck        # tsc --noEmit\npnpm lint             # biome check .\npnpm lint:fix         # biome check . --write\n```\n\nNo build step — Paseo loads plugin source directly. The loop after editing anything under\n`client/`, `server/`, or `shared/`:\n\n```bash\npaseo plugin reload sayr\npaseo plugin logs sayr   # confirm \"Plugin ready\" with no error\n```\n\nOnly run `pnpm install` at the repo root if you add a new dependency to `package.json`. Every RN\nclient file should stay free of DOM/Node APIs (`rg -n \"document\\.|window\\.|className=|onClick=\" client/`\nshould only ever match `client/web.ts`), and no async arrow functions in client code (a Hermes\nbug) — worth a quick grep before reloading if you touched anything under `client/`.\n\n## Known gaps\n\n- **Labels can be created but not edited or deleted.** `GET/POST /me/labels` and the labels picker\n  cover listing, selecting, and creating a label (with a public/private toggle), but there's no way\n  to rename, recolor, or delete an existing one from the plugin — that still needs the web app.\n- **Board doesn't show done/canceled tasks.** The status picker still covers the full status enum,\n  so a task can be moved there — it just drops off the board once it is.\n\n## Shoutouts\n\nInspiration of the layout & UI comes from gpambrozio's [github-board](https://github.com/gpambrozio/paseo-plugins/tree/main/github-board) plugin. Great resource for learning how to build Paseo plugins. <3"}