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

dailys-cli

v0.2.0

Published

Order lunch from Daily's Robotics without leaving the terminal.

Readme

dailys-cli

Lunch from Daily's Robotics, ordered from the terminal. The binary is dailys.

$ dailys signin order.dailys.inc/sutro/team-lunch --email [email protected] --name "Ana Reyes"
$ dailys menu --week
$ dailys order cabo --date tomorrow --diet "vegetarian, nut-free"
$ dailys my orders

It speaks dailys.ordering.v1 to api.dailys.inc over ConnectRPC, using the generated types in packages/proto and nothing hand written, so the CLI, the order page and the MCP server are three faces of one contract: MenuService for the published calendar, OrdersService for meals and tracking, AccountsService for the office manager, and TandemService for the event the CLI shipped for.

dailys mcp serves the same account to an AI agent over the Model Context Protocol, calling the same client core the commands call.

This is the consumer and office-manager CLI. Kitchen and staff tooling (Yoda) is deliberately out of scope and will arrive as its own binary; nothing in here reaches a staff RPC or asks anyone to sign in with a Daily's account.

Install

Once it is published:

npm install -g dailys-cli
dailys menu

From this repo, until then:

cd cli
npm install
npm run build
node dist/dailys.js menu

npm link inside cli/ puts dailys on your PATH pointing at that build. Running from source without a build works too: npm run dev -- menu.

Node 20 or newer.

Two doors

An ordering link is the door for everybody. dailys signin <link> --email --name is the whole of it: the link your office shared is the credential, exactly as it is in a browser, and the address and name are how the office and the kitchen name you rather than a second gate. Who may order is two rules and no more (Marco, Aug 7 2026): anyone holding a working ordering link, and anyone in the office's lunch channel on Slack once the bot is connected.

Two rules, and no third. A link is order.dailys.inc/<office>/<word>; the office's name on its own is not one of them, and joining with it is refused.

A manager key is the door to manager mode, and dailys login <key> is where it is used. Daily's mints one per account and shows it once. dailys open hands that session to a browser without a second sign-in.

Both write the same file and everything below behaves the same afterwards. A signed-out command that needs the wire says which door to use rather than just no.

Two surfaces, one binary

Signed in with an account key, menu and order are your company's ordering platform: a published calendar, meals on days, an order per day your office manager locks and sends to the kitchen.

Signed out, they are the Tandem event the CLI shipped for, unchanged: four bowls, one list per machine, no keys. dailys logout moves back.

Nothing else overlaps. my orders is the platform (the API's list, yours, on every machine you sign in from); orders is the event list this machine remembers. cancel is the platform; order remove is the event.

Your account

dailys signin <link> --email <address> --name "<name>"

The consumer door. The link is the one your office shared: the QR on the fridge, the line in the welcome email, the address in the lunch channel. Paste it whole (https://order.dailys.inc/sutro/team-lunch) or just its two words (sutro/team-lunch).

A link has a word on the end of it. The office's name alone (sutro) is not a link: it says which office and invites nobody, an office cannot turn it off when it leaks, and the API refuses a join that arrives with no link on it. Ask your office manager for the one they hand out.

$ dailys signin order.dailys.inc/sutro/team-lunch \
    --email [email protected] --name "Ana Reyes"

Signed in to Sutro Systems as Ana Reyes.

  you      [email protected]
  link     sutro/team-lunch
  lunch    $15.00 a bowl, you pay $3.00, 11:45 to 12:15
  saved    /Users/ana/.dailys/key.json

Next   dailys menu   dailys order <bowl> --date tomorrow

Both flags are required and neither is ever prompted for: this CLI reads nothing from a terminal, which is what lets the same line run under a script, a CI job and Commander. A link the office turned off is refused in the office's own words. Signing in again from the same link is fine and never makes a second you; the office knows you by your address.

Which link you used is remembered, so the office's board can say lunch came in through team-lunch rather than through web.

dailys login <key> / dailys logout / dailys whoami

The manager door. Daily's opens an account and hands its manager one key; it is shown once and never again, and everything in manager mode is behind it. It is checked with the API before it is written to ~/.dailys/key.json, mode 600, and it is never printed back whole.

$ dailys login dk_live_managerkey_c6d9

Signed in to Sutro Systems as a manager.

  key      dk_liv...c6d9
  api      https://api.dailys.inc
  saved    /Users/dana/.dailys/key.json

Next   dailys policy show   dailys members list   dailys day <date>

dailys whoami asks the API rather than guessing from the key: a manager key answers with the account and its policy, a member key answers with neither.

dailys open [--tab <name>] [--print]

Manager sessions only: this terminal's session, handed to a browser. The address carries the key once, the dashboard stores it and takes it straight back out of its own address bar, and no sign-in window stands in the way. Nothing is minted and nothing is rotated.

$ dailys open --print

Open the dashboard here.

  https://order.dailys.inc/company/sutro?key=dk_live_managerkey_c6d9

The link signs that browser in once and then takes itself out of the
address bar. Treat it like the key it carries.

The address is always printed, so a machine with no browser (SSH, CI) is one paste away. On macOS with a terminal attached the browser is opened as well.

dailys menu [--week] [--from DATE] [--to DATE]

Every published day in the window, closed days included and marked closed. The default window is the next 14 days, the horizon ordering opens for.

$ dailys menu

Menu   2026-08-04 to 2026-08-17

Tuesday, August 4
  KYOTO     Sweet Chili Shrimp & Coconut Jasmine Bowl
            pescatarian, dairy-free
  CABO      Barbacoa Taco Bowl
            gluten-free

Saturday, August 8
  closed

Order one   dailys order KYOTO --date 2026-08-04

dailys order <bowl> --date DATE [--diet TAGS] [--note TEXT]

One bowl, one day. The bowl can be named four ways: the recipe id, the kitchen code, the dish name, or any unambiguous case-insensitive prefix of one of those, resolved against that day's menu. A prefix that matches two bowls is not a guess the CLI will make for you.

$ dailys order cabo --date 2026-08-04 --diet "vegetarian, nut-free" --note "no cilantro"

Ordered.

  Barbacoa Taco Bowl (CABO)
  Tuesday, August 4
  diet vegetarian, nut-free
  note no cilantro

  $15.00   covered $12.00, you pay $3.00

  meal 5c705681-7669-4207-8ff0-583b01bb3f68
  order ord_1, open

Track it    dailys track 2026-08-04
Cancel it   dailys cancel 1

Dates are YYYY-MM-DD, or the words today and tomorrow. One bowl per person per day: cancel and order again to switch. The confirmation names the day in words and says what the company covers and what you owe, worked out from the account's policy by the server.

Ordering the same bowl for the same day twice is not two bowls. The second one comes back Already ordered. with the meal that is already there, so a double tap, a retried request or a bot that lost the answer never costs anybody a second lunch.

dailys usual <bowl> and dailys order usual --date DATE

Save the bowl you always order, once, and the order is one word after that.

$ dailys usual cabo

Your usual is Barbacoa Taco Bowl.

  bowl rcp_cabo

Order it   dailys order usual --date tomorrow

The bowl is resolved against the next two weeks of menus, so you can type its code or its name and it is saved as the recipe id the kitchen knows. A usual is not checked against any one day: menus rotate, and if it is not being served the day you ask for, the API says so and you pick something else that day. dailys usual none clears it.

dailys my orders [--from DATE] [--to DATE]

Yours, from the API, so it is the same list on every machine you sign in from.

$ dailys my orders

Your meals

  #1  Tue Aug 4   Barbacoa Taco Bowl  $15.00, you pay $3.00
                  diet vegetarian, nut-free
                  note no cilantro

Cancel one   dailys cancel 1
Track a day  dailys track <date>

dailys cancel <#|meal-id>

The number from dailys my orders, the full meal id, or an unambiguous prefix of it. A locked day cannot be canceled out of, and the API says so in its own words.

dailys track [<date>|<order-id>]

The status of that day's order for your account, and everything that has happened to it. With no argument, today.

$ dailys track 2026-08-04

Tuesday, August 4

  order    ord_1
  status   delivered
  goes to  5th floor kitchen, left of the sink

  09:12  Priya Rao ordered the Barbacoa Taco Bowl.
  09:41  Ada Lovelace ordered the Currylicious Tofu & Basmati Rice Bowl.
  10:02  Priya Rao canceled the Barbacoa Taco Bowl.
  11:00  Locked for the kitchen. 1 bowl going out.
  12:14  The van is stuck on the bridge.
  12:31  Delivered. 5th floor kitchen, left of the sink.

Every line is the server's sentence for that event. Status is one of open, locked, cooking, delivering, delivered, canceled. The kitchen can add a delayed line with a note; no new time is ever promised, because a promise that slips is the complaint.

If a bowl came off the menu after you ordered it, the tracker says so above the story and dailys my orders flags it. Nothing is ever cooked in its place without telling you:

  Sweet Chili Shrimp & Coconut Jasmine Bowl came off the menu that day. Pick another bowl.

dailys report <#|meal-id|date> --kind KIND [--note TEXT]

One command when something goes wrong: the wrong bowl, a missing one, a dietary restriction violated, late, cold, or something else. Give the number from dailys my orders (or a meal id) for one bowl, or a date when nothing arrived at all.

$ dailys report 1 --kind dietary --note "There were peanuts in it."

Reported.

  a diet problem on Tuesday, August 4
  There were peanuts in it.

  report iss_1

Your office manager and Daily's can both see this now. Somebody will
answer it in words, on the day's tracker.

See it   dailys track 2026-08-04

Kinds are dietary, wrong-item, missing, late, cold, other. No forms, no photographs of receipts, and dietary reports sort first everywhere they are listed.

dailys receipt <date> and dailys receipt --month / dailys spend

The money, about you. Both verbs answer at the tier of the key that asked: with a manager key they are the office's documents, described further down; with your own key they are yours, and the bottom line is what YOU paid, which is the number an expense form wants.

$ dailys receipt 2026-08-04

Your receipt   Tuesday, August 4

  Barbacoa Taco Bowl (CABO)     $15.00    company $12.00      you $3.00

  bowls      1
  subtotal   $15.00
  company    $12.00
  you paid   $3.00

Your month   dailys receipt --month
Your meals   dailys my orders

--month, --year and --from/--to turn either verb into the range document, day by day with a total on the end of it. dailys receipt --month and dailys spend --month are the same answer under the two names people reach for.

$ dailys spend --month

Your lunch   August 2026

  2026-08-01 to 2026-08-31

  bowls      9
  subtotal   $135.00
  company    $108.00
  you paid   $27.00

  Day by day

  Tue Aug 4   1 bowl    $15.00    company $12.00      you $3.00
  ...

Every share on it was charged when the office locked the day, so nothing here is a debt: it is money that has already moved. A day you ordered nothing on says so, and an empty range names the days it read.

The office manager

These need a manager key. A member key is turned away by the API, in the API's words.

dailys members list / dailys members add <name> --email ADDRESS [--role ROLE]

$ dailys members add "Priya Rao" --email [email protected]

Added Priya Rao.

  role     employee
  email    [email protected]
  member   mem_3

  key      dk_live_priyarao_c6d9

That key is shown once and cannot be shown again. Nobody has to be
sent it: Priya Rao orders by opening one of this office's
ordering links, the same as everybody else. Run `dailys links`.

Keep it only if a script or a bot is going to order as them.

Only the key's hash is stored, here and on the server, so there is nowhere to read it back from: send it when you see it, or add the person again to mint another. --json includes the key, for the one script that has to pipe it somewhere.

Roles are manager, employee and guest; employee is the default.

dailys policy show / dailys policy set <field> <value>

| Field | What it takes | | --- | --- | | coverage | the percent of every bowl the company pays, 0 to 100 | | meal-budget | the most it covers on one meal: 15, 15.50, none | | week-budget | the most it covers in one week: 60, none | | horizon | how many days ahead ordering opens: 14 | | access | qr-name, link-key, password or roster |

$ dailys policy set coverage 80

Updated.

  coverage       80% of every bowl
  meal budget    no cap
  week budget    no cap
  horizon        14 days ahead
  access         link-key

A value the field cannot take never leaves the machine (exit 2). A value the account cannot take is the server's call, and its refusal is what you see.

dailys day <date>

The delivery schedule: every member's meal for that day, grouped by bowl, with what the day costs.

$ dailys day 2026-08-04

Tuesday, August 4   open
  order ord_1

  CABO      Barbacoa Taco Bowl   2
    Priya Rao   vegetarian, nut-free   note no cilantro
    Ada Lovelace
  DELHI     Currylicious Tofu & Basmati Rice Bowl   1
    Zach Kim

  3 bowls   $45.00   covered $36.00, members pay $9.00

dailys lock <date>

Sends the day to the kitchen and closes ordering. One way: after it, nobody on the account can add or cancel a meal on that day, and dailys track says locked.

dailys delivery-note ["<text>"]

One standing note for the whole account: which floor, which fridge, which door and what the code is. Every day the account orders carries it, and it is repeated on the delivered line of the tracker, so "it says delivered and it is not here" has an answer written down before it is asked.

$ dailys delivery-note "5th floor kitchen, left of the sink"

Updated.

  5th floor kitchen, left of the sink

Every day this account orders carries that, and it is repeated on
the delivered line of the tracker.

With no argument it prints the note there is now. dailys delivery-note none clears it.

dailys issues [--open] and dailys resolve <#|id> --note TEXT

Everything anybody reported on the account, with what was done about it. Dietary reports sort first, then the newest.

$ dailys issues --open

Reports

  #1  Tue Aug 4    dietary     open
                   There were peanuts in it.
                   iss_1

  1 open report

Close one   dailys resolve 1 --note "What you did about it."

The sentence on resolve is not optional: it goes on the day's tracker, where the person who reported it reads it. "Resolved" with no words is what a chatbot does.

The Tandem event (signed out)

Unchanged, and still the whole product when no key is signed in.

dailys menu

What is being served: the bowl id, the title the event gave it, the dish, and the description.

$ dailys menu

On the menu

  kyoto     Thermal Simulation
            Sweet Chili Shrimp & Coconut Jasmine Bowl
            Broiled shrimp and blanched greens tossed in a glossy sweet chili
            glaze over coconut jasmine rice.

  ...

Order one   dailys order kyoto --for "Your Name"

dailys order <bowl> --for NAME [--diet TEXT]

Places one order and prints the confirmation, including the order id.

$ dailys order kyoto --for "Priya"
$ dailys order "Thermal Simulation" --for "Priya"
$ dailys order thermal --for "Priya" --diet "Vegetarian, Nut Free"

The bowl can be named by its exact id, its exact title, or any unambiguous case-insensitive prefix of either. hong and struct both find hongkong. A word that matches nothing goes to the server as typed, and the server answers in its own words.

dailys orders, dailys order edit <#|id>, dailys order remove <#|id>

The orders placed from this machine, numbered. This list is local: it reads ~/.dailys/orders.json and makes no network call. Editing and removing only reach orders in it, and anything not passed to an edit stays as it was, dietary notes included.

dailys tally

How many of each bowl are ordered so far, everyone's, for the kitchen's running count.

dailys health

Asks GET /health whether the API is up. Exits 0 when it answers and 1 when it does not, so it works in a shell test:

$ dailys health && echo "we can order"
https://api.dailys.inc is up.  (200, 41 ms)

Agents

Two ways to hand this account to an AI agent, for the two kinds of host there are.

A host that speaks MCP wants dailys mcp, below: the same capabilities as tools, gated by the tier of the key.

A host that drives the binary wants the skill. This package ships one, and installs it only when you ask:

$ dailys skill install

Installed the Daily's skill.

  /Users/ana/.claude/skills/dailys/SKILL.md

  Claude Code reads its skills when a session starts, so restart the
  one you are in for this to be there. After that, asking it about
  lunch, the menu, or the office's account reaches for this CLI.

Read it   dailys skill

It is one page: the two doors and how to tell which somebody needs, what each tier of key can do, and the laws an agent has to carry (resolve relative dates into explicit --from/--to because every read defaults forward, never claim emptiness from a window that did not cover the question, compose commands when no single verb fits, and get the user's yes before adding --yes to anything that cannot be undone).

dailys skill prints it, and dailys skill path says where the packed copy lives, for a host that reads skills from somewhere else. Nothing is written anywhere when you npm install this package: putting files in your home directory as a side effect of installing something is rude when it works and broken when it does not.

dailys mcp

A Model Context Protocol server on stdin and stdout, so an agent can read the menu, order lunch, cancel, and track a day the way you do at this prompt. It uses the key this machine is signed in with and can do exactly what that key can do.

{
  "mcpServers": {
    "dailys": {
      "command": "dailys",
      "args": ["mcp"],
      "env": { "DAILYS_KEY": "dk_live_..." }
    }
  }
}

| Tool | Key | What it does | | --- | --- | --- | | menu_days | any | the published calendar for a window, closed days marked | | place_meal | any | order one bowl for one day, or the word usual, resolved against that day | | cancel_meal | any | cancel one meal by id | | my_meals | any | the caller's meals in a window, with prices and coverage | | track_order | any | one day's status, its whole event log and the caller's meals | | report_issue | any | say something went wrong with a meal or a day | | day_order | manager | the delivery schedule for a day, with the roster and the totals | | lock_day | manager | send a day to the kitchen | | add_member | manager | add a person and mint their key, returned once | | set_policy | manager | change coverage, budgets, horizon or access mode | | list_issues | manager | what people reported, dietary first, open or all |

The manager tools are not listed at all for a member key: the server asks the API which tier it is holding before it answers tools/list, so a model never sees a tool it would only be refused for. Results are structured JSON, the same objects --json prints. A refusal comes back as an error result carrying the server's own sentence, which is exactly what an agent should relay to the person.

stdout carries the protocol, so anything a person would read goes to stderr.

Options

| Option | What it does | | --- | --- | | --api <url> | The API to talk to. Beats DAILYS_API. | | --json | Machine readable output, on every command that prints anything. | | -h, --help | Help for the CLI or for any one command. | | --version | The version and nothing else. |

Global options may come before or after the command: dailys --api http://localhost:8790 menu and dailys menu --api http://localhost:8790 are the same command.

Environment

  • DAILYS_API the API base URL. Defaults to https://api.dailys.inc. Point it at http://localhost:8790 to talk to a backend running locally (cd backend && npm run dev).
  • DAILYS_KEY an account key, beating the one on disk and writing nothing to it. This is how the MCP server is usually configured, and how a CI job orders lunch without a login.
  • DAILYS_HOME where the key and the local event order list live. Defaults to ~/.dailys.

What is on this machine

~/.dailys/key.json holds the account key, mode 600, in a directory mode 700. Nothing else about the account is cached: the menu, your meals and the day's order are all read from the API every time, so two machines never disagree.

{ "version": 1, "key": "dk_live_..." }

~/.dailys/orders.json remembers the Tandem event orders placed from this machine. It is what gives dailys orders its numbers and what lets edit and remove reach an order without a login: the CLI's version of the localStorage list the web order page keeps.

{
  "version": 1,
  "orders": [
    {
      "id": "df30bc1c-d30f-4de0-9478-aa9ac0a56df3",
      "name": "Priya",
      "bowlId": "cabo",
      "diet": "Vegetarian, Nut Free"
    }
  ]
}

Nothing secret is in that one, it is safe to delete (you lose the numbers, not the orders), and a mangled file is treated as an empty one rather than as a reason to stop working. The key file is treated the same way, which means a mangled key file reads as signed out.

Exit codes

| Code | When | | --- | --- | | 0 | It worked. | | 1 | The API or the order said no: a bowl that is not on that day's menu, a locked day, a manager's command on a member key, an API that is not answering, or no key on a machine that needs one. | | 2 | The command line did not make sense: an unknown command or option, a missing --date, a prefix matching two bowls, a policy value the field cannot take. |

Server messages are printed exactly as the server wrote them, because that copy is the product. The CLI's own messages are prefixed with dailys: so you can tell who is talking.

Development

npm install          # also installs packages/proto's dependency
npm run dev -- menu  # run from source through tsx
npm test             # vitest: both scripted sessions, the units, MCP, the built binary
npm run typecheck
npm run build        # bundles to dist/dailys.js, generated proto code included
npm run check        # typecheck + tests

The suite runs against a mock Daily's API: a real ConnectRPC server on an ephemeral port (test/mockApi.ts) implementing all four services from the generated descriptors, with an in-memory menu calendar, roster, keys, orders and event log, plus /health. It is this package's own implementation of the contract, not the backend's code, which is the point: two independent implementations of one proto file, meeting on the wire. It implements the semantics the contract describes in prose, because those are what the CLI has to be right about: key tiers, the ordering horizon, one bowl per person per day, locking, and the coverage math.

Two files are the product as scripted terminal sessions, in order, with exit codes: test/session.test.ts is a guest at the Tandem event, test/platform.session.test.ts is an office manager setting an account up and a new hire ordering lunch off it and being locked out. test/mcp.test.ts drives dailys mcp with a real MCP client over a linked in-memory transport, and test/built.smoke.test.ts runs the actual bundle as a child process, including one MCP handshake over real stdio.

No test may touch the internet. test/netGuard.ts replaces fetch with one that throws for every origin except the mock server a test started, and one of the tests points the CLI at production to prove the guard fires.

Publishing

npm publish from cli/. prepublishOnly runs the build and files ships dist/ and this README, nothing else. Bump version in package.json first: dailys --version reads it out of the bundle, where the build baked it in.

The bundle is self contained. The generated proto code, the Connect transport, the MCP SDK and zod are all inside dist/dailys.js, and nothing is resolved from node_modules at runtime, which is what makes npx dailys-cli and a copied-around binary work. The four dependencies are therefore build inputs that npm still installs for anyone who installs the package; moving them to devDependencies would make an install dist/ and nothing else, and is worth doing before the first publish if the MCP SDK's own tree (express, hono, ajv) is not something we want landing in people's node_modules for no reason.