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

@meeticarus/sdk

v0.0.3

Published

Carbon emissions SDK for AI inference and network data transfer. Zero dependencies, works out of the box with bundled emission factors.

Downloads

50

Readme

@meeticarus/sdk

Zero-dependency SDK for calculating carbon emissions from AI inference and network data transfer — works out of the box with bundled emission factors, no account required.

npm version license


Contents


Installation

npm install @meeticarus/sdk
# or
pnpm add @meeticarus/sdk
# or
yarn add @meeticarus/sdk

Zero runtime dependencies. Ships ESM + CJS with full TypeScript types.


Quick start

Option A — from raw token counts (synchronous, no dependencies):

import { trackAI } from "@meeticarus/sdk";

const result = trackAI({
  provider: "openai",
  model: "gpt-4o",
  inputTokens: 500,
  outputTokens: 200,
});

console.log(result.kgCO2e); // ~0.0000466 kg CO₂e
console.log(result.energyWh); // ~0.364 Wh
console.log(result.confidence); // "medium"

Option B — wrap a live provider call (token counts extracted automatically):

import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { withEmissions } from "@meeticarus/sdk/ai";

// anthropic() reads ANTHROPIC_API_KEY from the environment automatically
const { result, emission, latencyMs } = await withEmissions(() =>
  generateText({
    model: anthropic("claude-3-7-sonnet-20250219"),
    prompt: "Hello",
  }),
);

console.log(emission.kgCO2e); // ~0.0000466 kg CO₂e
console.log(emission.confidence); // "medium"
console.log(latencyMs); // wall-clock time for the API call

No Icarus account needed — both options use bundled emission factors out of the box. Option B requires your existing provider API key (OpenAI, Anthropic, etc.) to make the AI call, but nothing extra for emissions tracking.


Examples

Track AI emissions

Calculate the carbon footprint of a single AI call from raw token counts:

import { trackAI } from "@meeticarus/sdk";

const result = trackAI({
  provider: "openai",
  model: "gpt-4o",
  inputTokens: 1_000,
  outputTokens: 500,
});

console.log(result.kgCO2e); // e.g. 0.000412 — total emissions in kg CO₂e
console.log(result.energyWh); // total energy consumed in Wh (after PUE)
console.log(result.confidence); // "high" | "medium" | "low"
console.log(result.methodology); // "model-specific" | "median-fallback" | "size-class-fallback"

Region-aware tracking

Pass a region to use the appropriate grid carbon intensity for the electricity powering the inference:

import { trackAI } from "@meeticarus/sdk";

// UK grid (0.128 kg CO₂e/kWh — relatively clean, predominantly renewable)
const ukResult = trackAI({
  provider: "openai",
  model: "gpt-4o",
  inputTokens: 1_000,
  outputTokens: 500,
  region: "uk",
});

// French grid (0.041 kg CO₂e/kWh — predominantly nuclear)
const frResult = trackAI({
  provider: "openai",
  model: "gpt-4o",
  inputTokens: 1_000,
  outputTokens: 500,
  region: "fr",
});

// Supported: "us", "uk" (default), "eu", "de", "fr"
// Unknown regions fall back to the UK factor.

Unknown models with sizeHint

If a model isn't in the bundled factor table, the SDK falls back to a median energy profile. Provide a sizeHint to pick the closest size-class fallback instead:

import { trackAI } from "@meeticarus/sdk";

// claude-opus-4 isn't in the table yet — use sizeHint for a better estimate
const result = trackAI({
  provider: "anthropic",
  model: "claude-opus-4",
  inputTokens: 2_000,
  outputTokens: 800,
  sizeHint: "large", // "small" | "medium" | "large"
});

console.log(result.methodology); // "size-class-fallback"
console.log(result.confidence); // "low" — always "low" for fallbacks

// sizeHint guidance:
//   "small"  — lightweight / fast-tier  (e.g. Claude Haiku, Gemini Flash, GPT-4.1 nano)
//   "medium" — mid-tier frontier        (e.g. Claude Sonnet, GPT-4o-mini, GPT-4.1 mini)
//   "large"  — flagship / reasoning     (e.g. Claude Opus, GPT-4o, GPT-4.1)

Fetch live factors from the Icarus API

Bundled factors are updated with each SDK release. To always use the latest data without upgrading the package, fetch directly from the Icarus platform using an API key from your Icarus account:

Note: An Icarus API key is only needed here. Every other feature — trackAI, withEmissions, trackHTTP, and all provider wrappers — works entirely offline with bundled factors.

import { createClient, trackAI } from "@meeticarus/sdk";

const client = createClient({
  apiKey: process.env.ICARUS_API_KEY,
});

// Fetches once and caches for 24 hours by default
const factors = await client.fetchFactors();

const result = trackAI({
  provider: "openai",
  model: "gpt-4o",
  inputTokens: 1_000,
  outputTokens: 500,
  factors, // use the live factors from the API
});

You can force a cache refresh:

const freshFactors = await client.fetchFactors({ force: true });

Or configure a custom TTL (in milliseconds):

const client = createClient({
  apiKey: process.env.ICARUS_API_KEY,
  ttl: 6 * 60 * 60 * 1000, // refresh every 6 hours
});

// Set ttl: 0 to disable caching entirely
const noCacheClient = createClient({
  apiKey: process.env.ICARUS_API_KEY,
  ttl: 0,
});

Merge custom factors

Use createFactors() to layer your own overrides on top of the bundled defaults. Useful for region-specific utilities, internal energy measurements, or models not yet in the default table:

import { createFactors, trackAI } from "@meeticarus/sdk";

const factors = createFactors({
  // Replace the US grid intensity with your utility's measured value
  gridIntensity: [
    {
      region: "us",
      kgCO2ePerKWh: 0.21, // e.g. Pacific Northwest hydro mix
      source: "Your utility 2025 annual disclosure",
      validFrom: "2025-01-01",
    },
  ],
  // Add a model-specific factor for an internal fine-tuned model
  aiModels: [
    {
      provider: "acme",
      model: "acme-7b-fine-tuned",
      whPerInputToken: 1.1e-4,
      whPerOutputToken: 2.2e-4,
      pue: 1.18,
      source: "Internal measurement Q1 2025",
      confidence: "high",
      validFrom: "2025-01-01",
    },
  ],
});

const result = trackAI({
  provider: "acme",
  model: "acme-7b-fine-tuned",
  inputTokens: 500,
  outputTokens: 300,
  region: "us",
  factors,
});

Merge semantics:

  • aiModels — custom entries replace any default with the same provider + model; all other defaults are kept.
  • gridIntensity — custom entries replace any default with the same region; all others kept.
  • http — replaces the default entirely when provided.

Inspect the bundled factor tables

import { defaultFactors } from "@meeticarus/sdk";

// List all covered AI models
defaultFactors.aiModels.forEach((f) => {
  console.log(`${f.provider}/${f.model} — confidence: ${f.confidence}`);
});

// List bundled grid regions
defaultFactors.gridIntensity.forEach((g) => {
  console.log(`${g.region}: ${g.kgCO2ePerKWh} kg CO₂e/kWh`);
});

Reading the result

Every trackAI() call returns an EmissionResult with the full audit trail:

import { trackAI } from "@meeticarus/sdk";

const result = trackAI({
  provider: "openai",
  model: "gpt-4o",
  inputTokens: 1_000,
  outputTokens: 500,
  region: "uk",
});

// Top-level figures
result.kgCO2e; // total greenhouse gas emissions in kg CO₂e
result.energyWh; // total energy consumed in Wh (after PUE)
result.scope; // GHG Protocol scope — AI inference is always "3.1"

// Auditability
result.methodology; // "model-specific" | "median-fallback" | "size-class-fallback"
result.confidence; // "high" | "medium" | "low"
result.factorSource; // citation for the emission factor used

// Verbatim inputs recorded on the result
result.inputs.provider; // "openai"
result.inputs.model; // "gpt-4o"
result.inputs.inputTokens; // 1000
result.inputs.outputTokens; // 500
result.inputs.region; // "uk"

// Full calculation breakdown
result.breakdown.inputEnergyWh; // energy from input tokens (pre-PUE)
result.breakdown.outputEnergyWh; // energy from output tokens (pre-PUE)
result.breakdown.rawEnergyWh; // inputEnergyWh + outputEnergyWh
result.breakdown.pue; // data center overhead multiplier
result.breakdown.gridRegion; // "uk"
result.breakdown.kgCO2ePerKWh; // grid intensity applied

// Warnings — present when the model was not found in the factor table
if (result.warnings) {
  console.warn(result.warnings[0]);
  // e.g. "No emission factor found for 'anthropic/claude-future' — it may be a
  // newer model not yet in the bundled data. Pass sizeHint ('small' | 'medium' |
  // 'large') for a better estimate, or use createClient().fetchFactors()..."
}

Provider wrappers

If you're calling a provider API directly, the withEmissions() wrappers handle token extraction automatically. Install the wrapper for your provider — they are peer dependencies so you only install what you use.

Vercel AI SDK (recommended — works with any provider)

import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { withEmissions } from "@meeticarus/sdk/ai";

const { result, emission, latencyMs } = await withEmissions(() =>
  generateText({ model: openai("gpt-4o"), prompt: "Hello" }),
);

console.log(`${emission.kgCO2e.toExponential(2)} kg CO₂e (${latencyMs}ms)`);

Provider is inferred automatically from the model name — switching from openai("gpt-4o") to anthropic("claude-3-7-sonnet-20250219") requires no changes to your emissions tracking code.

For streamText, use trackAIResult() after the stream completes:

import { streamText } from "ai";
import { trackAIResult } from "@meeticarus/sdk/ai";

const stream = streamText({ model: openai("gpt-4o"), prompt: "Hello" });
for await (const chunk of stream.textStream) {
  /* ... */
}

const emission = trackAIResult({
  usage: await stream.usage,
  response: await stream.response,
});

OpenAI

import { withEmissions } from "@meeticarus/sdk/openai";

const { result, emission, latencyMs } = await withEmissions(() =>
  openai.chat.completions.create({
    model: "gpt-4o",
    messages: [{ role: "user", content: "Hello" }],
  }),
);

console.log(`${emission.kgCO2e.toExponential(2)} kg CO₂e (${latencyMs}ms)`);
// result is the unmodified OpenAI response

The model name is extracted from the response and normalised — "gpt-4o-2024-08-06""gpt-4o" — for accurate factor lookup.

Anthropic

import { withEmissions } from "@meeticarus/sdk/anthropic";

const { result, emission } = await withEmissions(() =>
  anthropic.messages.create({
    model: "claude-3-7-sonnet-20250219",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello" }],
  }),
);

console.log(`${emission.kgCO2e.toExponential(2)} kg CO₂e`);

Date suffixes are stripped automatically — "claude-3-7-sonnet-20250219""claude-3-7-sonnet".

Google Gemini

import { withEmissions } from "@meeticarus/sdk/google";

// Works with both @google/generative-ai and @google/genai
const { result, emission } = await withEmissions(
  () => model.generateContent("Hello"),
  { model: "gemini-2.0-flash" }, // recommended — not always in the response
);

console.log(`${emission.kgCO2e.toExponential(2)} kg CO₂e`);
// Gemini Flash carries confidence: "high" — first-party energy data from Google

Pass model in options — unlike OpenAI and Anthropic, the Gemini response does not always include the model name. If omitted, the wrapper falls back to response.modelVersion when available, then to a median estimate.

All wrappers accept the same optional second argument:

withEmissions(fn, {
  region: "uk", // grid region (default: "uk")
  factors, // live factors from createClient().fetchFactors()
  // Google only:
  model: "gemini-2.0-flash",
  sizeHint: "large", // fallback size class if model is unknown
});

Track HTTP emissions

Calculate the carbon footprint of network data transfer from raw byte counts. Useful for measuring the emissions from API responses, file downloads, or streaming:

import { trackHTTP } from "@meeticarus/sdk/carbon";

// Basic: bytes transferred → kgCO2e using the base data-transfer factor
const result = trackHTTP({ bytes: 1_500_000 }); // 1.5 MB

console.log(result.kgCO2e); // emissions in kg CO₂e
console.log(result.energyWh); // energy consumed in Wh
console.log(result.methodology); // "data-transfer"
console.log(result.scope); // "3.11" (use of sold products)

Use the category option to select a workload-specific energy profile:

// Heavy server-side compute — 2× the base factor
const heavyResult = trackHTTP({
  bytes: 1_500_000,
  category: "compute-heavy",
  region: "uk",
});

// Lighter options
trackHTTP({ bytes: 1_500_000, category: "cdn" }); // 0.06 kWh/GB (base)
trackHTTP({ bytes: 1_500_000, category: "api" }); // 0.07 kWh/GB
trackHTTP({ bytes: 1_500_000, category: "database" }); // 0.07 kWh/GB
trackHTTP({ bytes: 1_500_000, category: "streaming" }); // 0.08 kWh/GB
trackHTTP({ bytes: 1_500_000, category: "compute-heavy" }); // 0.12 kWh/GB

Tracked fetch

createFetchWithEmissions() wraps the standard fetch and automatically attaches an emission property to every response. The response body remains fully readable after the emission is calculated:

import { createFetchWithEmissions } from "@meeticarus/sdk/http";

const fetch = createFetchWithEmissions({ region: "uk", category: "api" });

const response = await fetch("https://api.example.com/data");

console.log(response.emission.kgCO2e); // kg CO₂e for this response
console.log(response.emission.inputs.bytes); // bytes measured

const data = await response.json(); // body still readable as normal

Byte size is measured from the Content-Length response header when present; otherwise the response body is read once to measure size (the original body stream remains unconsumed).

Inject a custom fetch implementation for testing:

const trackedFetch = createFetchWithEmissions({
  region: "us",
  fetch: myMockFetch,
});

API reference

trackAI(options): EmissionResult

Calculate emissions for a single AI inference call. Synchronous, browser-safe.

| Option | Type | Required | Default | Description | | -------------- | -------------------------------- | -------- | ---------------- | ----------------------------------------------------------------------------------- | | provider | string | Yes | — | Provider identifier, e.g. "openai", "anthropic" | | model | string | Yes | — | Model identifier, e.g. "gpt-4o" | | inputTokens | number | Yes | — | Number of input (prompt) tokens | | outputTokens | number | Yes | — | Number of output (completion) tokens | | region | string | No | "uk" | Grid region for carbon intensity lookup. Unknown regions fall back to the UK factor | | sizeHint | "small" \| "medium" \| "large" | No | — | Size-class fallback when model is unknown | | factors | Factors | No | defaultFactors | Override the entire factor table. Use createFactors() to merge with defaults |


createClient(options): IcarusClient

Create an authenticated client for fetching live emission factors from the Icarus API.

| Option | Type | Required | Default | Description | | --------- | -------- | -------- | ------------------------------ | ---------------------------------------------------- | | apiKey | string | Yes | — | Icarus API key (sent as Authorization: Bearer) | | baseUrl | string | No | "https://www.meeticarus.com" | Override for self-hosted deployments | | ttl | number | No | 86400000 (24h) | Cache lifetime in milliseconds. 0 disables caching |

client.fetchFactors(options?): Promise<Factors>

Fetches the latest Factors from GET /api/v1/factors/ai. Results are cached in memory for the configured ttl. Pass { force: true } to bypass the cache and re-fetch.

withEmissions(fn, options?) — provider wrappers

Exported from @meeticarus/sdk/openai, @meeticarus/sdk/anthropic, and @meeticarus/sdk/google.

| Provider | Import | Peer dependency | | ------------- | --------------------------- | --------------------------------- | | Vercel AI SDK | @meeticarus/sdk/ai | ai >= 4.0.0 | | OpenAI | @meeticarus/sdk/openai | openai >= 4.0.0 | | Anthropic | @meeticarus/sdk/anthropic | @anthropic-ai/sdk >= 0.20.0 | | Google Gemini | @meeticarus/sdk/google | @google/generative-ai >= 0.21.0 |

Returns { result, emission, latencyMs }. All peer dependencies are optional — install only the ones you use.


createFactors(overrides?): Factors

Merge custom factors with defaultFactors. Returns defaultFactors unchanged when called with no arguments.

import { createFactors } from "@meeticarus/sdk";

const factors = createFactors({
  gridIntensity: [...],
  aiModels: [...],
  http: { kWhPerGB: 0.05, source: "custom" },
});

trackHTTP(options): EmissionResult

Calculate emissions for a network data transfer. Synchronous, browser-safe. Exported from @meeticarus/sdk/carbon.

| Option | Type | Required | Default | Description | | ---------- | ---------------------------------------------------------------- | -------- | ---------------- | ----------------------------------------------------------------------------------- | | bytes | number | Yes | — | Total bytes transferred | | category | "cdn" \| "api" \| "database" \| "streaming" \| "compute-heavy" | No | — | Workload category for a more accurate energy estimate (see category profiles below) | | region | string | No | "us" | Grid region for carbon intensity lookup. Unknown regions fall back to the US factor | | factors | Factors | No | defaultFactors | Override the entire factor table. Use createFactors() to merge with defaults |

Category profiles

| Category | kWh/GB | Multiplier | Use case | | --------------- | ------ | ---------- | -------------------------------------------------- | | (default) | 0.06 | 1.0× | Generic data transfer (Shift Project / IEA 2022) | | cdn | 0.06 | 1.0× | Static assets from a CDN cache | | api | 0.07 | 1.17× | REST or GraphQL API responses | | database | 0.07 | 1.17× | Database query results | | streaming | 0.08 | 1.33× | Continuous audio/video streams | | compute-heavy | 0.12 | 2.0× | Heavy server-side compute (rendering, ML proxying) |


createFetchWithEmissions(options?)

Returns a fetch-compatible function that measures response size and attaches emission: EmissionResult to every response. Exported from @meeticarus/sdk/http.

| Option | Type | Required | Default | Description | | ---------- | ---------------------------------------------------------------- | -------- | ------------------ | ------------------------------------------------ | | region | string | No | "us" | Grid region for carbon intensity lookup | | category | "cdn" \| "api" \| "database" \| "streaming" \| "compute-heavy" | No | — | Workload category (see category profiles above) | | factors | Factors | No | defaultFactors | Override the entire factor table | | fetch | typeof globalThis.fetch | No | globalThis.fetch | Custom fetch implementation (useful for testing) |


defaultFactors

The full bundled Factors object: { aiModels, gridIntensity, http }. Import to inspect covered models, regions, sources, and confidence tiers.

import { defaultFactors } from "@meeticarus/sdk";
// same as:
import { defaultFactors } from "@meeticarus/sdk/carbon";

How it works

Each trackAI() call runs a three-step calculation:

rawEnergyWh = (inputTokens × whPerInputToken) + (outputTokens × whPerOutputToken)
energyWh    = rawEnergyWh × pue
kgCO2e      = (energyWh / 1000) × kgCO2ePerKWh
  • whPerInputToken / whPerOutputToken — model-specific energy per token, derived from published measurements or a size-class fallback profile.
  • pue (Power Usage Effectiveness) — data center overhead multiplier that accounts for cooling and infrastructure. Attached to each model factor (varies by provider/data center).
  • kgCO2ePerKWh — grid carbon intensity for the specified region.

Confidence tiers

| Tier | Meaning | | -------- | ----------------------------------------------------------------------- | | high | First-party data published by the provider | | medium | Peer-reviewed research (e.g. Jegham et al. 2025, arXiv:2505.09598) | | low | Statistical fallback — median or size-class profile from published data |

Methodologies

| Methodology | When used | | --------------------- | ---------------------------------------------------------------- | | model-specific | Exact provider/model found in the factor table | | size-class-fallback | Model not found; sizeHint provided | | median-fallback | Model not found; no sizeHint — uses the overall median profile | | data-transfer | HTTP byte-count tracking via trackHTTP() or tracked fetch |


Supported models and regions

Bundled AI models

| Provider | Models | | ------------- | --------------------------------------------------------------------------------------------------------------- | | OpenAI | gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, o1, o1-mini, o3, o3-mini, o4-mini | | Anthropic | claude-3-7-sonnet (other Claude models use sizeHint fallback) | | Google | gemini-1.5-flash, gemini-2.0-flash, gemini-2.5-flash | | DeepSeek | deepseek-r1, deepseek-v3 | | Meta | llama-3.1-8b, llama-3.1-70b, llama-3.3-70b |

Models not listed fall back automatically to the median profile. Use sizeHint for a better estimate.

Bundled grid regions

| Region | Grid intensity | Source | | -------------- | ----------------- | ------------------------------------------------- | | us | 0.386 kg CO₂e/kWh | EPA eGRID 2024 / IEA 2025 | | uk (default) | 0.128 kg CO₂e/kWh | DEFRA/DESNZ 2025 | | eu | 0.175 kg CO₂e/kWh | IEA Electricity 2025 | | de | 0.331 kg CO₂e/kWh | IEA Emissions Factors 2025 | | fr | 0.041 kg CO₂e/kWh | IEA Emissions Factors 2025 | | cn | 0.6 kg CO₂e/kWh | IEA / Jegham et al. 2025 — China national average |

Unknown regions fall back to the US factor. Add any region via createFactors().


Get an Icarus account

trackAI() works immediately with no account using the bundled factor tables, which are updated with each SDK release.

To always use the latest factors without upgrading the SDK, connect to the Icarus API:

  1. Sign up at www.meeticarus.com
  2. Create your organisation during onboarding
  3. Generate an API key from your dashboard settings
  4. Pass it to createClient():
const client = createClient({ apiKey: process.env.ICARUS_API_KEY });
const factors = await client.fetchFactors();

const result = trackAI({ ..., factors });

For enterprise pilots or bespoke integrations, reach out at [email protected].


License

MIT — see LICENSE.