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

catshit

v1.1.1

Published

Terminal arcade game — cats hit object, race the CPU to the catch position

Downloads

86

Readme

🐱 catshit

npm node

Pure terminal. Pure ASCII. No browser, no Electron, no cloud, no accounts.


   ██████╗ █████╗ ████████╗███████╗██╗  ██╗██╗████████╗
  ██╔════╝██╔══██╗╚══██╔══╝██╔════╝██║  ██║██║╚══██╔══╝
  ██║     ███████║   ██║   ███████╗███████║██║   ██║
  ██║     ██╔══██║   ██║   ╚════██║██╔══██║██║   ██║
  ╚██████╗██║  ██║   ██║   ███████║██║  ██║██║   ██║
   ╚═════╝╚═╝  ╚═╝   ╚═╝   ╚══════╝╚═╝  ╚═╝╚═╝   ╚═╝

         Cats hit something. You race the CPU.
               First to catsh it wins.



                        ╭─╮
      /\_/\            ─┴─┴─       /\_/\
     (^.^= )~          (°-°)      ( =^.^)>
      UU-UU             ´H`        UU-U´

Install

npm install -g catshit

Requires Node.js 18 or later.

Play

catshit

🕹️ How to play

Aiming — lock 3 timing bars

Before each throw, three bars bounce back and forth. Hit the key to lock each one in sequence:

| Bar | What it controls | |-----|-----------------| | Strength | How hard the cats hit — affects distance | | Angle | Launch angle — affects height vs. distance trade-off | | Mass | Object weight — affects speed, drag, and bounciness |

| Key | Action | |-----|--------| | Space or Enter | Lock the current bar | | Backspace | Cancel → back to settings |

In flight — race to the spot

Once the object launches, you and the CPU both race to stand under the landing position. The CPU samples the arc and predicts where it'll land. So do you — except you can see the whole arc.

| Key | Action | |-----|--------| | / A | Move left | | / D | Move right | | Shift + ←/A | Sprint left | | Shift + →/D | Sprint right | | Space | Jump — catch mid-air at the apex | | Enter | Commit catch at current position | | Q / Ctrl+C | Quit |

You don't need to press Enter to catch — standing under the landing spot when it hits the ground counts too. But committing early (Enter) lets you score while the CPU is still running.

After each round

| Key | Action | |-----|--------| | Any key | Play again | | M | Return to main menu |


📋 Game modes

Demo

Free play. Before each throw you can tune hit strength, launch angle, object, wind, and gravity. Nothing saves. Great for getting a feel for the physics.

Campaign

Seven handcrafted levels with increasing CPU speed and physics challenges. Each level has:

  • A specific object (ball, feather, or rock)
  • A fixed CPU CPM (calculations per minute — how fast the CPU predicts)
  • Optional physics modifiers (altered gravity, max wind, drag)
  • Up to three stretch goals that award bonus points and ⭐ stars

Win a level to unlock the next. Progress saves automatically to ~/.catshit.json.


💩 Objects

| Object | Mass | Drag | Bounciness | |--------|------|------|------------| | Default | 1.0 | 0 | 0 | | Ball | 1.0 | 0.02 | 0.3 — bounces away on a CPU win | | Feather | 0.2 | 0.08 | 0.1 — floats, drifts with wind | | Rock | 2.5 | 0.005 | 0.05 — fast and heavy |

Heavier objects travel farther and are less affected by drag. Objects with bounciness roll away after a CPU win, giving you a visual cue that you lost.


🏆 Scoring

Score = gap × time

| Component | What it measures | |-----------|-----------------| | Gap score | How far the CPU was from the landing spot when you committed | | Time score | How many seconds faster you were than the CPU would have arrived | | Goal bonuses | Flat point bonuses for hitting level objectives | | Hat bonuses | Wearable hats extend your mid-air catch range (Y-axis tolerance) |

Points accumulate across all rounds. Spend them in the Shop on consumables and wearable hats.


🧩 Mods

catshit is built mod-first. The official campaign, all objects, and all cosmetics ship as built-in mods. You can add your own.

Enabling mods

Main menu → Mods — toggle any installed mod on or off. Your selections are saved to ~/.catshit.json.

Installing a mod

Drop a folder containing a mod.json into the mods/ directory next to the catshit package install (e.g. node_modules/catshit/mods/my-mod/mod.json).

mod.json — full schema

{
  "id": "my-mod",
  "name": "My Mod",
  "version": "1.0.0",
  "core": false,

  "content": {

    "menuItems": [
      { "label": "My Campaign", "action": "CAMPAIGN" }
    ],

    "objects": [
      {
        "id": "rubber-duck",
        "name": "Rubber Duck",
        "mass": 0.5,
        "dragCoefficient": 0.04,
        "bounciness": 0.6
      }
    ],

    "campaign": {
      "id": "my-campaign",
      "name": "My Campaign",
      "levels": [
        {
          "id": "level-1",
          "name": "First Throw",
          "hitStrength": 14,
          "cpuCpm": 70,
          "objectId": "rubber-duck",
          "modifiers": { "wind": 2, "gravity": 9.8 },
          "physics": { "minLaunchAngle": 30, "maxLaunchAngle": 60 },
          "goals": [
            { "type": "distance_gt",          "value": 30, "label": "Land past col 30",    "scoreBonus": 20 },
            { "type": "altitude_gt",           "value": 10, "label": "Reach altitude 10",   "scoreBonus": 15 },
            { "type": "catch_within_seconds",  "value": 5,  "label": "Catch within 5s",     "scoreBonus": 25 }
          ]
        }
      ]
    },

    "shopItems": [
      {
        "id": "power-throw",
        "name": "Power Throw",
        "description": "Boosts hit strength by 5 for one throw",
        "price": 500,
        "category": "consumable",
        "effect": {
          "type": "modify_config",
          "params": { "minHitStrength": 17, "maxHitStrength": 27 }
        }
      }
    ],

    "cosmetics": [
      {
        "id": "duck-hat",
        "assetType": "hat",
        "spriteAnchor": 2,
        "poses": {
          "idle":  [">v<"],
          "catch": [">v<"],
          "miss":  [">v<"]
        }
      },
      {
        "id": "duck-face",
        "assetType": "face",
        "poses": {
          "idle":  ["(o_o)"],
          "catch": ["(°o°)"],
          "miss":  ["(;_;)"]
        }
      }
    ],

    "cpuStrategies": [
      { "id": "my-strategy", "module": "strategy.js" }
    ]

  }
}

Extension points

| Type | What it adds | |------|-------------| | objects | New throwable objects with custom physics (mass, drag, bounciness) | | campaign | Full campaign — levels, goals, physics modifiers, object overrides | | menuItems | Extra entries injected into the main menu | | shopItems | Purchasable consumables with modify_config effects applied at throw time | | cosmetics | Hat, face, body, outfit, and full cat sprite replacements | | cpuStrategies | Custom CPU AI — a JS module that receives the full arc and returns updated CPU state |

Goal types

| Type | Condition | |------|-----------| | distance_gt | Landing position > value (columns) | | distance_lt | Landing position < value | | altitude_gt | Peak height > value | | altitude_lt | Peak height < value | | hangtime_gte | Time airborne >= value (seconds) | | catch_within_seconds | Player catches within N seconds of launch |

Each goal that is met adds scoreBonus points and counts as one ⭐ star.

Writing a CPU strategy

A strategy module exports a single default function. It receives the current CPU state and arc data, and returns a new CPU state:

// strategy.js
export default function myStrategy(cpu, arc, arcComplete, tick, arcFrame, wind) {
  // cpu         — { position, prediction, samples, arrived, ... }
  // arc         — [{ x, y }, ...] full trajectory (world coordinates)
  // arcComplete — true when the full arc is visible
  // tick        — current game tick
  // arcFrame    — leading arc frame index (only frames up to here are "visible")
  // wind        — per-throw lateral force (positive = rightward)

  // Move directly to the landing point once arc is complete
  if (arcComplete) {
    const landing = arc[arc.length - 1];
    return { ...cpu, position: landing.x, arrived: true, prediction: landing };
  }

  return cpu; // do nothing until arc is complete
}

🔮 What's next

  • 📦 Community content — more objects, campaigns, cosmetics and CPU strategies via mods
  • 🐾 More cat skins — full cat sprite replacements via the cat cosmetic type

The mod extension points are stable. Community mods are welcome.


Uninstall

npm uninstall -g catshit

No ads. No subscriptions. No online requirement. Just cats hitting, an object, and a race to the catch.