npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cemoody/pi-crust-ext-todoist

v0.1.1

Published

Interactive, mobile-friendly Todoist widget for pi-crust — the LLM drives your task list via tools while you edit/complete tasks inline in the sidebar.

Readme

@cemoody/pi-crust-ext-todoist

An interactive, mobile-friendly Todoist widget for pi-crust. The LLM drives your task list with tools; you edit, complete, and reschedule tasks inline in the sidebar. Both surfaces operate on the same Todoist account, so changes the agent makes show up immediately in the widget and vice-versa.

Without a TODOIST_API_TOKEN the extension runs against a fully-interactive in-memory mock (create / edit / complete / reopen / delete all work) so you can try it offline. Set the token to talk to your real account.

Three surfaces, one client

This package wires three pi-crust/pi entry points to a single shared Todoist REST client (todoist-client.mjs):

| File | Manifest key | Role | |---------------------|-------------------------|------| | pi.mjs | pi.extensions | LLM-facing tools — the agent driving surface | | server.mjs | piCrust.extension | Registers the Todoist sidebar activity + /api/ext/todoist/* REST routes | | web.mjs | piCrust.web | The interactive React widget mounted in the sidebar |

The widget calls the server routes; the agent tools call Todoist directly. Both go through the same client, so there's no state to keep in sync — Todoist (or the mock store) is the single source of truth.

The UI paradigm

A deliberately focused subset of Todoist rather than a full clone — what you actually want inline in a session:

  • Project chips across the top scope the list (All + each project, with live open-task counts). Horizontally scrollable on phones.
  • A sticky quick-add bar creates tasks into the active project (Inbox by default). Enter or the Add button.
  • Each task row is a large tap target:
    • a round complete checkbox colored by priority (P1 red → P4 grey) with a satisfying strike-and-remove animation,
    • the title is tap-to-edit inline (Enter saves, Esc cancels),
    • a due-date chip (overdue = red, today = green, otherwise a friendly date),
    • project dot (in the All view) and @label pills,
    • row actions to cycle priority and delete (hover-revealed on desktop, always visible on phones).
  • Every mutation is optimistic and reconciles against the server response.

It collapses to a single comfortable column with 44px+ tap targets under 640px, and reuses the host design tokens so it matches the rest of pi-crust.

Agent tools

| Tool | Description | |--------------------|-------------| | todoist_list | List active tasks (by projectId or a Todoist filter query like today, overdue, @work & p1) | | todoist_projects | List projects with ids | | todoist_add | Create a task (content, dueString natural language, priority 1–4, labels, projectId) | | todoist_update | Edit a task (content, dueString, clearDue, priority, labels, projectId) | | todoist_complete | Complete (close) a task | | todoist_reopen | Reopen a completed task | | todoist_delete | Delete a task |

Priority follows the Todoist REST convention: 4 = P1 (urgent)1 = P4.

Inline tool-call cards

Every agent tool call renders a compact Todoist summary inline in the conversation timeline (not just a line of text). The tools attach a details.piRemoteControlArtifact of kind markdown to their result; pi-crust renders it natively in the timeline. We use markdown (not HTML) on purpose: HTML artifacts are wrapped in a bordered figure and a bordered, 320px-min sandboxed iframe, which double-boxes a small task list, leaves dead whitespace, and can't run scripts anyway. Markdown renders organically in a single box with the host's own typography.

When the agent runs todoist_list, todoist_add, todoist_complete, or todoist_update, you see the affected list right in the chat — a just-added task is bolded, completed tasks are struck through, and a status line (Added · Work, Completed · 3 still open) heads the card.

The inline card is a read-only snapshot. pi-crust sandboxes artifact iframes (sandbox="", no scripts), so inline items can't be tapped to mutate. The interactive surface is the sidebar panel.

Editing in the sidebar (interactive)

The sidebar Todoist panel is where you work with tasks directly:

  • Tap the round check → completes the task (with strike animation).
  • Tap the title → inline text editor; Enter saves, Esc cancels.
  • Tap the priority flag → cycles P1→P4 (todoist_update priority).
  • Tap the due chip (or the faint 📅 Due on undated tasks) → a natural-language due editor (“tomorrow 9am”, “next monday”); clear it to remove the date.
  • Quick-add at the top; trash to delete.

All mutations are optimistic and proxied to the /api/ext/todoist/* routes.

Tests

Built test-first (vitest + jsdom + Testing Library):

npm test

Covers the inline-artifact builder (test/artifact.test.mjs — markdown shape, highlight, status, due labels), the agent tools' artifact wiring (test/pi-tools.test.mjs), and the sidebar widget interactions (test/widget.test.mjs — complete, title edit, priority cycle, due-date editing, quick-add).

Connecting your account

Two ways to provide a Todoist personal API token (Todoist → Settings → Integrations → Developer → API token):

  1. In-app (recommended) — open the Todoist panel and use the Connect your Todoist account banner. The token is saved via prc.storage to …/todoist.json and survives restarts. A Disconnect link clears it.
  2. Env var — set TODOIST_API_TOKEN (handy for headless/server/CI).

Token resolution precedence: an in-app (stored) token wins; otherwise the env var; otherwise the interactive in-memory demo store. The connection status endpoint returns only a masked hint (…cdef) — the raw token is never sent to the browser.

| Env var | Purpose | |---------------------|---------| | TODOIST_API_TOKEN | Optional fallback token. In-app token takes precedence; when neither is set the in-memory mock is used. |

Config routes: GET /api/ext/todoist/config, POST /api/ext/todoist/token {token}, POST /api/ext/todoist/token/delete. Full surface + edge cases: docs/SPEC-token-config.md.

Publishing

Ships an allow-listed tarball (9 files; verify with npm pack --dry-run). prepublishOnly runs the test suite. To publish:

npm version patch        # or minor/major
npm publish --access public
# or: push a vX.Y.Z tag and let .github/workflows/publish.yml do it (needs NPM_TOKEN)

Until published, install from a path or git URL:

PI_CRUST_EXTENSIONS=/path/to/pi-crust-ext-todoist npx pi-crust
# or add the path/git url to packages[] in your pi-crust settings.json

Install

Pi-crust discovers any installed package whose package.json carries a piRemoteControl / piCrust field; pi discovers the pi.extensions entry.

TODOIST_API_TOKEN=xxxx PI_CRUST_EXTENSIONS=/path/to/pi-crust-ext-todoist npx pi-crust

REST surface (used by the widget)

GET  /api/ext/todoist/state?projectId=        -> { projects, tasks, live }
POST /api/ext/todoist/tasks                    { content, projectId? } -> { task }
POST /api/ext/todoist/tasks/:id/update         { content?, priority?, dueString?, ... } -> { task }
POST /api/ext/todoist/tasks/:id/close          -> { ok }
POST /api/ext/todoist/tasks/:id/reopen         -> { ok }
POST /api/ext/todoist/tasks/:id/delete         -> { ok }

Preview

node preview/shoot.mjs renders the widget against an in-memory mock and writes preview/desktop.png + preview/mobile.png (requires playwright-core).

License

MIT.