Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
30 changes: 30 additions & 0 deletions .github/actions/setup-nix/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Setup Nix
description: Install Nix and configure Cachix
inputs:
cachix-auth-token:
description: Cachix authentication token
required: false
runs:
using: composite
steps:
- name: Install Nix
uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0
with:
github_access_token: ${{ github.token }}

- name: Setup Cachix (numtide)
uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
name: numtide
authToken: ''

- name: Setup Cachix (ryoppippi)
if: inputs.cachix-auth-token != ''
uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
name: ryoppippi
authToken: ${{ inputs.cachix-auth-token }}

- name: Load Nix development environment
shell: bash
run: nix develop --command true
45 changes: 18 additions & 27 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,45 @@ jobs:
runs-on: ubuntu-24.04-arm

steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup-nix
- run: nix develop --command pnpm lint
- run: nix develop --command pnpm typecheck

test:
runs-on: ubuntu-24.04-arm

steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- run: pnpm install --frozen-lockfile
- name: Check jq is available
run: which jq && jq --version
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup-nix
- name: Create default Claude directories for tests
run: |
mkdir -p $HOME/.claude/projects
mkdir -p $HOME/.config/claude/projects
- run: pnpm run test
- run: nix develop --command pnpm run test

npm-publish-dry-run-and-upload-pkg-pr-now:
runs-on: ubuntu-24.04-arm

steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- run: pnpm install --frozen-lockfile
- run: pnpm dlx pkg-pr-new@0.0.60 publish --pnpm './apps/*'
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup-nix
- run: nix develop --command pnpm pkg-pr-new publish --pnpm './apps/*'

spell-check:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout Actions Repository
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1

- uses: crate-ci/typos@master
with:
config: ./typos.toml
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup-nix
- run: nix develop --command typos --config ./typos.toml

schema-check:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- run: pnpm install --frozen-lockfile
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup-nix
- name: Generate schema files
run: pnpm run generate:schema
run: nix develop --command pnpm run generate:schema
working-directory: apps/ccusage
- name: Check if schema files are up-to-date
run: |
Expand Down
19 changes: 9 additions & 10 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,33 @@ on:

jobs:
npm:
runs-on: ubuntu-slim
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
- uses: ./.github/actions/setup-nix
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
registry-url: 'https://registry.npmjs.org'
node-version: lts/*
- run: pnpm install --frozen-lockfile
- run: pnpm --filter='./apps/**' publish --provenance --no-git-checks --access public
- run: nix develop --command pnpm --filter='./apps/**' publish --provenance --no-git-checks --access public
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

actions/setup-node registry-url NODE_AUTH_TOKEN authentication

💡 Result:

Short answer: actions/setup-node writes an .npmrc that reads the auth token from the NODE_AUTH_TOKEN environment variable when you pass registry-url (and optional scope). You must set NODE_AUTH_TOKEN in the workflow’s env (usually from a secret such as NPM_TOKEN or GITHUB_TOKEN). For GitHub Packages you can use GITHUB_TOKEN for packages in the same repo; for other private registries use a personal access token with appropriate scopes. Examples and docs below. [1][2][3]

Example (minimal):

  • name: Use Node.js
    uses: actions/setup-node@v4
    with:
    node-version: '20.x'
    registry-url: 'https://registry.npmjs.org' # or https://npm.pkg.github.com for GPR
  • name: Install
    run: npm ci
    env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # or ${{ secrets.GITHUB_TOKEN }} when allowed

What setup-node creates in .npmrc:
//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
registry=https://registry.npmjs.org/
always-auth=true

References:
[1] actions/setup-node (GitHub repo/docs).
[2] GitHub Actions docs — Use setup-node + example showing NODE_AUTH_TOKEN usage.
[3] GitHub Packages / npm registry auth guidance (GITHUB_TOKEN vs personal access token).


🌐 Web query:

npm publish OIDC provenance GitHub Actions authentication

💡 Result:

Short answer — yes. You can publish npm packages from GitHub Actions using OIDC-based authentication and produce/verifiy provenance. High-level steps and requirements:

  1. Requirements
    • npm CLI: >=9.5.0 to generate/consume provenance; npm >=11.5.1 for npm “trusted publishing” (OIDC-based publishes without static tokens). [1][2]
  2. Workflow permissions (GitHub Actions)
    • Give the job permission to mint an ID token: permissions: id-token: write. Use GitHub-hosted runners (self-hosted not supported for provenance/trusted publishing). [1][2]
  3. Publish with provenance (older flow or explicit)
    • Build on a supported cloud CI runner (GitHub Actions).
    • Run npm publish --provenance (and --access public if first public publish). npm will use Sigstore to sign provenance and upload to Rekor; registry verifies provenance on publish. [1][4]
  4. Trusted publishing (OIDC-backed, recommended)
    • Configure a “trusted publisher” in your npm package settings (establishes which workflow file may publish).
    • With trusted publishing, the registry accepts short‑lived, workflow-specific credentials issued via OIDC; provenance is produced automatically (no --provenance needed). You can publish without storing long‑lived NPM tokens in secrets. Requires npm CLI v11.5.1+ and cloud runner. [2][5]
  5. Notes / limitations
    • Provenance/trusted publishing currently requires public source repositories for provenance; private repos may not get provenance. Some npm commands (install/view) still need traditional auth for other operations (and private package installs may require a read token). Each package can have one trusted publisher at a time. [1][2][6]

Pointers / docs

  • Generating provenance / GitHub Actions example (npm docs). [1]
  • Trusted publishing docs (how to configure and limits). [2]
  • GitHub Actions npm-publish action notes (supports OIDC if npm version supports trusted publishing). [3]
  • npm provenance implementation/details (npm’s provenance repo). [4]

If you want, I can: (A) generate a ready-to‑use GitHub Actions workflow (with permissions, setup-node, npm publish) for your repo and npm version, or (B) walk through configuring a trusted publisher in the npm web UI — which do you want?


🏁 Script executed:

cat -n .github/workflows/release.yaml

Repository: ryoppippi/ccusage

Length of output: 1376


🏁 Script executed:

# Check if there's a .npmrc file in the repository that might provide implicit authentication
find . -maxdepth 2 -name ".npmrc" -type f

Repository: ryoppippi/ccusage

Length of output: 43


Add explicit NODE_AUTH_TOKEN environment variable for npm publishing.

The workflow configures setup-node with registry-url but does not explicitly set NODE_AUTH_TOKEN. While setup-node creates the .npmrc structure to read authentication from the environment, it requires NODE_AUTH_TOKEN to be explicitly provided in the job's env block. Add NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} (or equivalent) to the npm job's environment, or alternatively, ensure the npm version (>=11.5.1) supports OIDC-based trusted publishing and configure it in your npm package settings to publish without storing long-lived tokens.

🤖 Prompt for AI Agents
.github/workflows/release.yaml around line 24: the publish step does not set
NODE_AUTH_TOKEN so setup-node cannot populate .npmrc auth; add NODE_AUTH_TOKEN:
${{ secrets.NPM_TOKEN }} to the npm job's env block (or the job that runs the
publish command) so the workflow supplies the token to npm during publish;
alternatively, if you intend to use OIDC-based trusted publishing, configure npm
>=11.5.1 and package settings instead, but the immediate fix is to set
NODE_AUTH_TOKEN from secrets.NPM_TOKEN in the job env.


release:
needs:
- npm
runs-on: ubuntu-slim
runs-on: ubuntu-24.04-arm
permissions:
contents: write
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
- run: bunx changelogithub@13.16.0
- uses: ./.github/actions/setup-nix
- run: nix develop --command pnpm changelogithub
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
.DS_Store

.eslintcache

# nix
.direnv
!.envrc
20 changes: 20 additions & 0 deletions apps/ccusage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,26 @@ npx ccusage monthly --compact # Compact monthly report

Full documentation is available at **[ccusage.com](https://ccusage.com/)**

## Development Setup

### Using Nix (Recommended for Contributors)

For contributors and developers working on ccusage, we provide a Nix flake-based development environment:

```bash
# Clone the repository
git clone https://github.com/ryoppippi/ccusage.git
cd ccusage

# Allow direnv (automatically loads Nix environment)
direnv allow

# Or manually enter the development shell
nix develop
```

This ensures consistent tooling versions across all contributors and CI systems. The development environment is defined in `flake.nix` and automatically activated via direnv when entering the project directory.

## Sponsors

### Featured Sponsor
Expand Down
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
description = "Usage analysis tool for Claude Code";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
# Package manager
pnpm_10

# Development tools
typos
jq
git
gh
];
Comment on lines +16 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Node.js is missing from buildInputs.

The flake provides pnpm_10 but doesn't include Node.js itself. The package.json specifies Node.js ^24.11.0 in devEngines, but the Nix development shell doesn't provide it. This will cause the development environment and CI workflows to fail since pnpm and the project require Node.js to function.

Apply this diff to add Node.js to buildInputs:

         buildInputs = with pkgs; [
+          # Runtime
+          nodejs_24
+
           # Package manager
           pnpm_10
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
buildInputs = with pkgs; [
# Package manager
pnpm_10
# Development tools
typos
jq
git
gh
];
buildInputs = with pkgs; [
# Runtime
nodejs_24
# Package manager
pnpm_10
# Development tools
typos
jq
git
gh
];
🤖 Prompt for AI Agents
In flake.nix around lines 16 to 25, buildInputs contains pnpm_10 but omits
Node.js causing pnpm and project tooling to fail; add the appropriate Node.js
package (matching project engine, e.g., nodejs-24_x or nodejs-24) from pkgs to
buildInputs alongside pnpm_10 so the development shell and CI have Node
available; ensure you import it from pkgs (with pkgs; [ nodejs-24_x pnpm_10 ...
]) and run nix flake update/test to verify the environment provides the correct
Node version.


shellHook = ''
# Install dependencies only if node_modules/.pnpm/lock.yaml is older than pnpm-lock.yaml
if [ ! -f node_modules/.pnpm/lock.yaml ] || [ pnpm-lock.yaml -nt node_modules/.pnpm/lock.yaml ]; then
echo "📦 Installing dependencies..."
pnpm install --frozen-lockfile
fi
'';
};
}
);
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
"@ryoppippi/eslint-config": "catalog:lint",
"@typescript/native-preview": "catalog:types",
"bumpp": "catalog:release",
"changelogithub": "catalog:release",
"eslint": "catalog:lint",
"lint-staged": "catalog:release",
"oxfmt": "catalog:lint",
"pkg-pr-new": "catalog:release",
"sitemcp": "catalog:mcp",
"sort-package-json": "catalog:release"
},
Expand Down
Loading
Loading