Skip to content
Back to skills

Cocometer

ASecurity

Generate the CocoMeter Enhanced HTML dashboard. Queries SNOWFLAKE.ACCOUNT_USAGE.CORTEX_CODE_CLI_USAGE_HISTORY, joins with local request-map.jsonl attribution data, injects into meter-view.html.template, and opens in browser.

  • 724 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 5, 2026
ai-agentsshellsqlgit

Works with

  • cli

Security analysis

A100/100

Pro scans all 20 files and shows the line behind each finding

Scanned September 5, 2026

npx -y skills add Snowflake-Labs/cocoplus --skill cocometer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Cocometer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Cocometer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/snowflake-labs-cocometer-fffa12dc/badge)](https://www.skillsdirectory.com/skills/snowflake-labs-cocometer-fffa12dc)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "meter-view"
description: "Generate the CocoMeter Enhanced HTML dashboard. Queries SNOWFLAKE.ACCOUNT_USAGE.CORTEX_CODE_CLI_USAGE_HISTORY, joins with local request-map.jsonl attribution data, injects into meter-view.html.template, and opens in browser."
version: "2.0.0"
author: "CocoPlus"
tags:
  - cocoplus
  - cocometer
  - cocometer-enhanced
---

Your objective is to generate and open the CocoMeter token attribution dashboard.

## CocoPlus 2.0 Console-Aware Redirect

Before generating standalone HTML, check `.cocoplus/lifecycle/console-state.json`.

If the file exists and contains `running: true` with a `port` value:
1. Output: `Opening Cost panel in CocoConsole.`
2. Open `http://localhost:<port>/cost` in the browser.
3. Stop. Do not generate a standalone snapshot.

If CocoConsole is not running, continue with the standalone CocoMeter dashboard behavior below.

## Pre-flight Check

Check that `.cocoplus/` exists. If not:
Output: "CocoPlus not initialized. Run $pod init to begin." Then stop.

## Read Attribution Data

Read `.cocoplus/meter/request-map.jsonl`. If the file is missing or empty, continue — the dashboard must still render with local-only data and zero Snowflake rows. Use an injected payload shaped like:

```json
{
  "local_only": true,
  "rows": [],
  "stages": [],
  "warning": "No local CocoMeter request-map entries were found yet."
}
```

Partition entries into two sets:
- **Direct IDs:** entries where `is_subagent_anchor` is absent or false
- **Anchor IDs:** entries where `is_subagent_anchor` is true

## Query Snowflake Usage History

If any Direct IDs exist, execute Pass 1:
```sql
SELECT REQUEST_ID, PARENT_REQUEST_ID, USAGE_TIME, TOKENS, TOKEN_CREDITS,
       TOKENS_GRANULAR, CREDITS_GRANULAR
FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_CODE_CLI_USAGE_HISTORY
WHERE REQUEST_ID IN (<direct_ids>)
   OR PARENT_REQUEST_ID IN (<direct_ids>)
ORDER BY USAGE_TIME ASC;
```

If Anchor IDs also exist, execute Pass 2:
```sql
SELECT REQUEST_ID, PARENT_REQUEST_ID, USAGE_TIME, TOKENS, TOKEN_CREDITS,
       TOKENS_GRANULAR, CREDITS_GRANULAR
FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_CODE_CLI_USAGE_HISTORY
WHERE PARENT_REQUEST_ID IN (<anchor_ids>)
  AND REQUEST_ID NOT IN (<pass_1_request_ids>)
ORDER BY USAGE_TIME ASC;
```

Union Pass 1 and Pass 2 results. If either query fails (permission denied, connection error), log the error and continue with whatever was retrieved — do not abort.

## Join and Aggregate

Join Snowflake rows with `request-map.jsonl`:
- Direct rows: match on `REQUEST_ID`
- Pass-2 rows: resolve `stage_id` by matching `PARENT_REQUEST_ID` to anchor records in `request-map.jsonl`
- Unmatched rows: `stage_id = "unattributed"`

Compute summary aggregations:
- Total tokens, total credits
- Cache efficiency %: `cache_read_input / (input + cache_read_input + cache_write_input) * 100`
- Total output tokens
- Per-stage and per-model breakdowns

Serialise the merged dataset as JSON.

## Locate the HTML Template

Locate `templates/meter-view.html.template` relative to the installed CocoPlus plugin root. Do not hard-code an OS-specific plugin directory.

Read the template. If missing:
Output: "CocoMeter template not found in the CocoPlus plugin templates directory. Re-install or update the CocoPlus plugin." Then stop.

## Inject Meter Data

Find the injection block:
- Start: `/* __METER_INJECTION_START__ */`
- End: `/* __METER_INJECTION_END__ */`

Replace with:
```js
const INJECTED_METER_DATA = <serialised_json>;
```

## Write and Open

Write the injected HTML to `.cocoplus/meter-view.html` atomically (write to `.tmp`, then rename).

Write sync metadata: `.cocoplus/meter/last-sync.json`:
```json
{ "last_sync": "<ISO timestamp>", "row_count": <n> }
```

Open `.cocoplus/meter-view.html`:
- macOS: `open .cocoplus/meter-view.html`
- Linux: `xdg-open .cocoplus/meter-view.html`
- Windows: `powershell -Command "Invoke-Item '.cocoplus/meter-view.html'"`

## Output

With Snowflake data:
```
✓ CocoMeter dashboard generated.
  Stages: <N>  |  Requests: <N>  |  Snowflake rows: <N>
  Total tokens: <N>  |  Cache efficiency: <N>%
  Opening: .cocoplus/meter-view.html
```

If Snowflake returned no rows:
```
⚠ No usage data from Snowflake yet.
  CORTEX_CODE_CLI_USAGE_HISTORY has up to 90-minute latency.
  Dashboard generated with local attribution data only.
  Run $meter sync after ~90 minutes to refresh.
  Opening: .cocoplus/meter-view.html
```

If browser open failed:
```
✓ CocoMeter dashboard generated.
  Could not open browser automatically.
  Open this file manually: .cocoplus/meter-view.html
```

## Anti-Rationalization

| Shortcut / Temptation | Why It Fails |
|-----------------------|--------------|
| Abort if Snowflake query fails | Partial data is still valuable; the dashboard renders in local-only mode gracefully |
| Abort because request-map.jsonl is missing | A new project still needs a usable dashboard shell; render a local-only empty dashboard |
| Skip atomic write for meter-view.html | A mid-write crash would leave a corrupt file that the browser opens as blank |
| Skip last-sync.json update | `$meter sync` uses this to show when data was last refreshed |

## Exit Criteria

- [ ] `.cocoplus/meter-view.html` written with `INJECTED_METER_DATA` containing merged Snowflake + local data
- [ ] `.cocoplus/meter/last-sync.json` updated with current timestamp and row count
- [ ] Output reports stage count, request count, total tokens, and cache efficiency
- [ ] No git commit created (dashboard is ephemeral, gitignored)

Files in this skill

  • archetype-classifier.skill.md1.5 KB
  • chargeback-refresh.skill.md1.5 KB
  • cost-center-resolver.skill.md1.5 KB
  • invoice-generator.skill.md1.5 KB
  • meter-accuracy.skill.md2.3 KB
  • meter-benchmark.skill.md1.3 KB
  • meter-chargeback.skill.md3.2 KB
  • meter-compare.skill.md4.1 KB
  • meter-estimate.skill.md3.4 KB
  • meter-history.skill.md1.9 KB
  • meter-invoice.skill.md1.5 KB
  • meter-off.skill.md2.3 KB
  • meter-on.skill.md2.3 KB
  • meter-reconcile.skill.md4.1 KB
  • meter-refresh.skill.md1.5 KB
  • meter-report.skill.md3.5 KB
  • meter-status.skill.md1.5 KB
  • meter-sync.skill.md2 KB
  • meter-verify.skill.md1.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…