{"id":8919883,"url":"https://github.com/github-copilot-resources/copilot-metrics-viewer","last_synced_at":"2026-07-01T06:00:43.492Z","repository":{"id":213068750,"uuid":"732798198","full_name":"github-copilot-resources/copilot-metrics-viewer","owner":"github-copilot-resources","description":"Tool to visualize the Copilot metrics provided via the Copilot Business Metrics API ","archived":false,"fork":false,"pushed_at":"2026-06-24T17:54:17.000Z","size":10728,"stargazers_count":623,"open_issues_count":13,"forks_count":322,"subscribers_count":19,"default_branch":"main","last_synced_at":"2026-06-24T18:22:35.770Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://copilot-metrics-viewer-gthcc5cmd9ebf2ff.westeurope-01.azurewebsites.net/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/github-copilot-resources.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS.md","security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-17T21:18:50.000Z","updated_at":"2026-06-22T07:27:16.000Z","dependencies_parsed_at":"2026-04-22T07:01:01.331Z","dependency_job_id":null,"html_url":"https://github.com/github-copilot-resources/copilot-metrics-viewer","commit_stats":null,"previous_names":["martedesco/copilot-metrics-viewer","github-copilot-community/copilot-metrics-viewer","github-copilot-resources/copilot-metrics-viewer"],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/github-copilot-resources/copilot-metrics-viewer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-copilot-resources%2Fcopilot-metrics-viewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-copilot-resources%2Fcopilot-metrics-viewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-copilot-resources%2Fcopilot-metrics-viewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-copilot-resources%2Fcopilot-metrics-viewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/github-copilot-resources","download_url":"https://codeload.github.com/github-copilot-resources/copilot-metrics-viewer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-copilot-resources%2Fcopilot-metrics-viewer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34994877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-05-02T01:08:16.764Z","updated_at":"2026-07-01T06:00:43.484Z","avatar_url":"https://github.com/github-copilot-resources.png","language":"TypeScript","funding_links":[],"categories":["Bicep","TypeScript"],"sub_categories":[],"readme":"_NOTE: For information on support and assistance, click [here](https://github.com/github-copilot-resources/copilot-metrics-viewer/tree/main?tab=readme-ov-file#support)._\n\n\u003e **ℹ️ v3.0 — New Copilot Usage Metrics API**\n\u003e\n\u003e As of v3.0, Copilot Metrics Viewer uses the [Copilot Usage Metrics API](https://docs.github.com/en/enterprise-cloud@latest/rest/copilot/copilot-usage-metrics). The legacy Copilot Metrics API was shut down on April 2, 2026 and is no longer available.\n\u003e\n\u003e **What's new in v3.0:**\n\u003e - Uses the async Copilot Usage Metrics API for all data\n\u003e - **Historical mode** with PostgreSQL for data beyond the 28-day rolling window\n\u003e - **Per-user metrics** tab with individual usage breakdowns\n\u003e - **Team metrics derived from per-user data** — no longer requires the deprecated team-level API endpoints\n\u003e - Sync service for automated daily data collection\n\u003e\n\u003e Your GitHub App needs **\"Organization Copilot metrics: Read\"** permission. See [GitHub App Registration](./DEPLOYMENT.md#github-app-registration) for setup details.\n\n# GitHub Copilot Metrics Viewer\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"150\" alt=\"image\" src=\"https://github.com/github-copilot-resources/copilot-metrics-viewer/assets/3329307/8473a694-217e-4aa2-a3c7-2222a321c336\"\u003e\n\u003c/p\u003e\n\nThis application displays a set of charts with various metrics related to GitHub Copilot for your \u003ci\u003eGitHub Organization\u003c/i\u003e or \u003ci\u003eEnterprise Account\u003c/i\u003e. These visualizations are designed to provide clear representations of the data, making it easy to understand and analyze the impact and adoption of GitHub Copilot. \n\n## Operating Modes\n\nThe application supports two operating modes:\n\n| Mode | Description | Requirements | Team Metrics | Data Retention |\n|------|-------------|--------------|--------------|----------------|\n| **Direct API** | Fetches metrics directly from GitHub's API on each page load | GitHub token only | ❌ Not available | Rolling 28 days |\n| **Historical Mode** | Reads from a local PostgreSQL database, synced daily | PostgreSQL + Sync service | ✅ Full history | Unlimited |\n\n**Direct API mode** is the simplest setup — no database required. It returns the latest 28-day rolling window of data from the [Copilot Usage Metrics API](https://docs.github.com/en/enterprise-cloud@latest/rest/copilot/copilot-usage-metrics). Team-scoped views are not available in this mode because team metrics are derived from per-user records stored in the database.\n\n**Historical mode** adds a PostgreSQL database and a sync service that downloads metrics daily. This enables:\n- Viewing metrics **beyond the 28-day API window**\n- **Per-user time-series history** with trend charts\n- **Team metrics** — derived from stored per-user data filtered by team membership\n\nSee [DEPLOYMENT.md](./DEPLOYMENT.md) for setup instructions for each mode.\n\n## Application Overview\n\nThe GitHub Copilot Metrics Viewer provides comprehensive analytics through an intuitive dashboard interface:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Main Dashboard Overview\" src=\"./images/main-metrics-dashboard.png\"\u003e\n\u003c/p\u003e\n\n## New Features\n\n### Date Range Filtering (up to 100 days)\nUsers can now filter metrics for custom date ranges up to 100 days, with an intuitive calendar picker interface. The system also supports excluding weekends and holidays from calculations.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Date Range Filter\" src=\"./images/date-range-filter.png\"\u003e\n\u003c/p\u003e\n\n### Teams Tab\nSelect **one team** for a full deep-dive view with KPI tiles, time-series charts (acceptance rate, active users, feature usage, model usage), language and editor breakdowns, and a per-user activity table. Select **two or more teams** to compare them side by side.\n\n\u003e [!NOTE]\n\u003e GitHub's Copilot Usage Metrics API does not provide team-level endpoints. Team metrics are **derived** by fetching per-user daily metrics from the organization/enterprise endpoint, resolving team membership via the GitHub Teams API, and aggregating per-user data in-memory. This works in both Direct API mode (28-day window) and Historical mode (full history).\n\n**Single team deep dive:**\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Teams Single Team Deep Dive\" src=\"./images/teams-single-team.png\"\u003e\n\u003c/p\u003e\n\n**Multi-team comparison:**\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Teams Comparison\" src=\"./images/teams-comparison.png\"\u003e\n\u003c/p\u003e\n\n#### Team-Scoped Direct URLs\n\nYou can link directly to a fully team-scoped dashboard — every tab (IDE metrics, chat, agents, languages, etc.) will automatically filter to that team's members only. A blue banner at the top of the page confirms the active scope and provides a quick link back to the organization view.\n\n```\nhttps://\u003cyour-host\u003e/orgs/\u003corg\u003e/teams/\u003cteam\u003e\nhttps://\u003cyour-host\u003e/enterprises/\u003centerprise\u003e/teams/\u003cteam\u003e\n```\n\nExamples:\n- `http://localhost:3000/orgs/octo-demo-org/teams/the-a-team`\n- `http://localhost:3000/enterprises/octo-demo-ent/teams/the-a-team`\n- `http://localhost:3000/orgs/mocked-org/teams/the-a-team?mock=true` _(mock data)_\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Team-scoped dashboard showing blue banner with team name and Back to Org button\" src=\"./images/team-scoped-dashboard.png\"\u003e\n\u003c/p\u003e\n\n### Per-User Metrics\nView individual user-level Copilot usage metrics including code completions, chat interactions, and code review activity. Summary tiles show total users, active users, and average acceptance rate.\n\nIn **Historical mode** (with PostgreSQL), the User Metrics tab also displays per-user time-series history charts, allowing you to track individual adoption trends over time.\n\nThe per-user table includes an **AI Credits** column showing each user's premium-request spend (sourced from the `ai_credits_used` field that GitHub added to the `users-28-day` Copilot metrics report on 2026-06-19). The column shows `—` when GitHub hasn't reported credits for the period (e.g., older mock data or enterprises that haven't enabled premium-request billing).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Per-User Metrics\" src=\"./images/user-metrics.png\"\u003e\n\u003c/p\u003e\n\n### My Usage Tab\nPersonal dashboard for the currently-authenticated user. Shows your own active days, interactions, accepted lines, AI credits used, top IDE, and top model — filtered server-side by `session.user.login` so you can never see another user's data from this tab.\n\nVisible to every authenticated user when any auth provider is configured (`NUXT_PUBLIC_AUTH_PROVIDERS`). Hidden when the app is running in PAT-only / no-auth mode, because there is no session user to filter by.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"My Usage tab — personal AI credit spend, CLI token usage, and daily charts\" src=\"./images/my-usage.png\"\u003e\n\u003c/p\u003e\n\n### Billing (admin)\nAggregate AI credit billing breakdown by model, SKU, cost center, and repository — pulled from the GitHub Billing API (`/organizations/{org}/settings/billing/ai_credit/usage` and `/enterprises/{ent}/settings/billing/ai_credit/usage`). Also includes a **per-user breakdown table** that joins the org's user list with each user's billing spend (lazy-loaded one page at a time), with \"Top spenders by net cost\" and \"Top CLI token users\" charts.\n\n**Visibility:**\n1. **When `NUXT_GITHUB_BILLING_TOKEN` is *not* configured** — the tab is shown to every dashboard user, but renders only a configuration-help placeholder (no data is fetched). This is a discoverability aid so operators learn the feature exists.\n2. **When `NUXT_GITHUB_BILLING_TOKEN` *is* configured** — the tab is **admin-only**: visible only to users on the `NUXT_USAGE_ADMINS` allowlist. In PAT-mode deployments (no OAuth provider configured) the allowlist is bypassed and the tab is visible to anyone who can reach the dashboard.\n\n**Why a separate token?** Billing endpoints have stricter auth than metrics endpoints — they require a **classic PAT** with `manage_billing:enterprise` (or `manage_billing:copilot`), SSO-authorized for the target enterprise. Fine-grained PATs and GitHub Apps cannot read billing today. Keeping `NUXT_GITHUB_BILLING_TOKEN` separate from `NUXT_GITHUB_TOKEN` means your metrics calls can keep using a GitHub App / fine-grained PAT while only billing uses the classic PAT.\n\n**Enterprise-owned orgs:** when a dashboard's org is consolidated under an enterprise (very common), `/organizations/{org}/settings/billing/ai_credit/usage` returns **404**. Set `NUXT_BILLING_ENTERPRISE=\u003centerprise-slug\u003e` to route billing calls to `/enterprises/{slug}/...` regardless of the dashboard's scope. Without this override an org-scoped dashboard will see a 404 with a hint pointing at the variable.\n\n**Per-user attribution caveat:** the per-user breakdown depends on GitHub tagging each billing item with a `user`. Some enterprise plans (typically fully-pooled / centrally-billed) return only enterprise-level aggregates, in which case every user appears at $0 in the per-user table; the Billing tab surfaces an explanatory alert in that state. The My Usage tab and the User Metrics `ai_credits_used` column are independent of this and still work.\n\n#### Admin drill-down — inline User insights per user\n\nEach username in the Per-user breakdown table is a clickable chip. Selecting a chip reveals an inline **User insights** section directly below the table with that user's full Copilot activity report — the same view the user would see on their own My Usage tab (Active days, Interactions, Accepted lines, AI credits used, per-model spend, top IDE / language / model, day-by-day charts).\n\nNo user selected → the section shows an info banner explaining the feature. Clicking a chip a second time (or \"Clear selection\") returns to the banner state.\n\n**Requires** the same `NUXT_GITHUB_BILLING_TOKEN` + `NUXT_BILLING_ENTERPRISE` variables as the rest of the Billing tab. The drill-down endpoint (`/api/my-usage?login=\u003cother\u003e`) is gated by `NUXT_USAGE_ADMINS`; non-admins receive 403. In PAT-only deployments the operator is admin-by-PAT and the drill-down works without an OAuth session.\n\n![Billing tab — Per-user breakdown with chip-style logins and the info banner state](images/billing-user-insights-banner.png)\n\n![Billing tab — inline User insights section showing a selected user's activity](images/billing-user-insights-selected.png)\n\n#### Billing CSV Ingest (local cache, multi-month windows)\n\nThe live billing endpoints cap windows at ~31 days and rate-limit aggressively. For longer historical analysis, the dashboard can pull GitHub's **enterprise billing CSV exports** into a local Postgres table, then serve the Billing tab from the cache.\n\nWhen the cache covers the selected window, the Billing tab serves data from the DB and shows a small \"Source: local cache\" chip with the last-synced timestamp. When the window is partially or not covered, it falls back to the live API automatically.\n\n**Triggering an ingest** (admin panel → Billing CSV ingest):\n- Pick a date range (defaults to last 30 days through today)\n- Leave **\"Skip already-ingested ranges\"** checked to fetch only the gaps in your selected window — re-running for an overlapping range becomes cheap\n- Submit; the job runs in the background, polled by the recent-jobs table\n\nGitHub builds the export server-side and returns one or more signed download URLs (60-minute TTL). The ingester downloads, parses, dedupes by primary key, and bulk-upserts into the `billing_credit_usage` table. Multi-month windows are chunked at ≤31 days internally — you can request months of data in a single click.\n\nThe recent-jobs table shows status, row count, who triggered, and a hover tooltip on the row count surfacing **what was fetched vs. skipped** (so you can verify gap-mode actually pruned re-fetches of already-ingested ranges).\n\n**Requires:** `NUXT_GITHUB_BILLING_TOKEN` set to a classic PAT with `manage_billing:enterprise` (same token used by the live Billing tab) plus `NUXT_BILLING_ENTERPRISE` for the enterprise slug. Postgres must be configured (see the storage section).\n\n![Admin panel — Billing CSV ingest controls](images/billing-csv-ingest.png)\n\n![Billing tab with per-user breakdown sourced from the local cache](images/billing-tab-cache.png)\n\n### My Usage (per-user, self-service)\nPersonal Copilot activity for the signed-in user only — server-side filtered against the session. Surfaces:\n- `ai_credits_used` totals + per-day chart (when a date range is selected)\n- **Your AI credit spend** — total $, credits billed, per-model breakdown (requires `NUXT_GITHUB_BILLING_TOKEN`; the call always sends `?user=\u003csession-login\u003e` and is never user-controllable)\n- GitHub CLI usage card (sessions, requests, prompt/output token sums, CLI version) when the user has CLI activity\n- AI adoption-phase chip and top-IDE/plugin versions\n\n### Models Tab\nView model usage analytics including model adoption over time, chat model distribution, and usage per chat mode (Ask, Agent, Edit, Inline).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Models Tab\" src=\"./images/models-tab.png\"\u003e\n\u003c/p\u003e\n\n### CSV Export Functionality\nExport your metrics data in multiple formats for further analysis or reporting. Options include summary reports, full detailed exports, and direct clipboard copying.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"CSV Export Options\" src=\"./images/csv-export-functionality.png\"\u003e\n\u003c/p\u003e\n\n## Charts\n\n## Key Metrics\n\u003e[!NOTE]\n\u003e Metrics details are described in detail in the [Copilot Usage Metrics API documentation](https://docs.github.com/en/enterprise-cloud@latest/rest/copilot/copilot-usage-metrics)\n\nHere are the key metrics visualized in these charts:\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Key Metrics Overview\" src=\"./images/main-metrics-dashboard.png\"\u003e\n\u003c/p\u003e\n\n1. **Active Users Over Time:** Tracks daily, weekly, and monthly active users across all Copilot features — IDE completions, chat, agent mode, CLI, and PR summaries.\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Active Users Over Time\" src=\"./images/Acceptance_rate_bycount.png\"\u003e\n\u003c/p\u003e\n\n2. **Feature Usage Over Time:** Shows user-initiated interactions per feature per day, covering IDE chat, agent mode, edit mode, inline chat, CLI, PR summaries, and more.\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Feature Usage Over Time\" src=\"./images/Total_suggestions_count.png\"\u003e\n\u003c/p\u003e\n\n3. **Code Completions:** Tracks total inline code suggestions shown and accepted over time.\n\n4. **Total Lines Suggested:** Showcases the total number of lines of code suggested by GitHub Copilot. This gives an idea of the volume of code generation and assistance provided.\n\n5. **Total Lines Accepted:** As the name suggests, the total lines of code accepted by users (full acceptances) offering insights into how much of the suggested code is actually being utilized and incorporated into the codebase.\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"image\" src=\"./images/Total Lines.png\"\u003e\n\u003c/p\u003e\n\n6. **Total Active Users:** Represents the number of active users engaging with GitHub Copilot. This helps in understanding the user base growth and adoption rate.\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"image\" src=\"./images/Total_Active_users.png\"\u003e\n\u003c/p\u003e\n\n## Languages Breakdown Analysis\n\nPie charts with the top 5 languages by accepted prompts and acceptance rate (by count/by lines) are displayed at the top.\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Updated Language breakdown with charts and data table\" src=\"./images/languages-breakdown.png\"\u003e\n\u003c/p\u003e\n\nThe language breakdown analysis tab also displays a table showing the Accepted Prompts, Accepted Lines of Code, and Acceptance Rate (%) for each language over the selected time period. The entries are sorted by the number of _accepted lines of code descending_.\n\n## Copilot Chat Metrics\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Copilot Chat Metrics Dashboard\" src=\"./images/copilot-chat-metrics.png\"\u003e\n\u003c/p\u003e\n\n1. **Cumulative Number of Turns:** This metric represents the total number of turns (interactions) with the Copilot over the selected time period. A 'turn' includes both user inputs and Copilot's responses.\n\n2. **Cumulative Number of Acceptances:** This metric shows the total number of lines of code suggested by Copilot that have been accepted by users over the selected time period.\n\n3. **Total Turns | Total Acceptances Count:** This is a chart that displays the total number of turns and acceptances.\n\n4. **Total Active Copilot Chat Users:** A bar chart that illustrates the total number of users who have actively interacted with Copilot over the selected time period.\n\n## Seat Analysis\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"800\" alt=\"Seat Analysis Dashboard\" src=\"./images/seat-analysis.png\"\u003e\n\u003c/p\u003e\n\n1. **Total Assigned:** This metric represents the total number of Copilot seats assigned within the current organization/enterprise.\n\n2. **Assigned But Never Used:** This metric shows seats that were assigned but never used within the current organization/enterprise. The assigned timestamp is also displayed in the chart.\n\n3. **No Activity in the Last 7 Days:** Never used seats or seats used, but with no activity in the past 7 days.\n\n4. **No Activity in the Last 7 Days (including never used seats):** A table to display seats that have had no activity in the past 7 days, ordered by the date of last activity. Seats that were used earlier are displayed at the top.\n\n## Advanced Features\n\n### Flexible Date Range Selection\nThe application supports flexible date range selection allowing users to analyze metrics for any period up to 100 days. The date picker provides an intuitive calendar interface with options to exclude weekends and holidays from the analysis.\n\n### Data Export Capabilities\nMultiple export options are available in the API Response tab:\n- **Download CSV (Summary)**: Exports key metrics in a condensed format\n- **Download CSV (Full)**: Exports comprehensive detailed data\n- **Copy Metrics to Clipboard**: Quick copy functionality for immediate use\n- **Check Metric Data Quality**: Validates data integrity and completeness\n\n### Team Analytics\nOrganizations can compare metrics across different teams to:\n- Identify high-performing teams\n- Understand adoption patterns\n- Share best practices across teams\n- Monitor team-specific engagement levels\n\n\u003e [!NOTE]\n\u003e Team metrics are derived from per-user data by resolving GitHub team membership and aggregating. The GitHub Copilot Usage Metrics API does not have dedicated team endpoints — this application computes team views automatically. In Direct API mode, team data covers the latest 28-day window. In Historical mode (with PostgreSQL), full historical team trends are available.\n\n### Model Usage Analytics\nDetailed insights into AI model usage including:\n- IDE Code Completions by editor and model type\n- IDE Chat interactions and model preferences\n- GitHub.com Chat usage patterns\n- PR Summary generation statistics\n- Custom vs. default model adoption rates\n\n## Setup Instructions\n\nIn the `.env` file, you can configure several environment variables that control the behavior of the application.\n\nPublic variables:\n- `NUXT_PUBLIC_IS_DATA_MOCKED`\n- `NUXT_PUBLIC_SCOPE`\n- `NUXT_PUBLIC_GITHUB_ENT`\n- `NUXT_PUBLIC_GITHUB_ORG`\n- `NUXT_PUBLIC_HIDDEN_TABS`\n- `NUXT_PUBLIC_ENABLE_HISTORICAL_MODE`\n\ncan be overridden by route parameters, e.g.\n- `http://localhost:3000/enterprises/octo-demo-ent`\n- `http://localhost:3000/orgs/octo-demo-org`\n- `http://localhost:3000/orgs/octo-demo-org/teams/the-a-team`\n- `http://localhost:3000/enterprises/octo-demo-ent/teams/the-a-team`\n- `http://localhost:3000/orgs/mocked-org?mock=true`\n\nWhen navigating to a team-scoped URL, a blue banner appears at the top confirming the active team scope and offering a **Back to org** button. All tabs automatically filter to team members only.\n\n#### NUXT_PUBLIC_SCOPE (Required!)\n\nThe `NUXT_PUBLIC_SCOPE` environment variable in the `.env` file determines the default scope of the API calls made by the application. It can be set to `'enterprise'` or `'organization'`.\n\n- If set to `'enterprise'`, the application will target API calls to the GitHub Enterprise account defined in the `NUXT_PUBLIC_GITHUB_ENT` variable.\n- If set to `'organization'`, the application will target API calls to the GitHub Organization account defined in the `NUXT_PUBLIC_GITHUB_ORG` variable.\n- To view team-level metrics, use the Teams tab or navigate to `/orgs/\u003corg\u003e/teams/\u003cteam\u003e` — team filtering is applied as a post-processing step.\n\n\u003e **Note:** Legacy values `'team-organization'` and `'team-enterprise'` are still accepted and automatically normalized to `'organization'` and `'enterprise'` respectively for backward compatibility.\n\nFor example, if you want to target the API calls to an organization, you would set `NUXT_PUBLIC_SCOPE=organization` in the `.env` file.\n\n\u003e[!INFO]\n\u003e Environment variables with `NUXT_PUBLIC` scope are available in the browser (are public).\n\u003e See [Nuxt Runtime Config](https://nuxt.com/docs/guide/going-further/runtime-config) for details.\n\n````\nNUXT_PUBLIC_SCOPE=organization\n\nNUXT_PUBLIC_GITHUB_ORG=\u003cYOUR-ORGANIZATION\u003e\n\nNUXT_PUBLIC_GITHUB_ENT=\n````\n\n#### NUXT_PUBLIC_IS_DATA_MOCKED\n\nVariable is false by default. To view mocked data switch it to true or use query parameter `?mock=true`.\n\n````\nNUXT_PUBLIC_IS_DATA_MOCKED=false\n````\n\n#### NUXT_GITHUB_TOKEN\n\nSpecifies the GitHub Personal Access Token utilized for **metrics** API requests. Generate this token with the following permissions: _Read access to members_, _organization copilot metrics_, and _organization copilot seat management_.\n\nThis token does **not** need billing scopes — billing has its own dedicated token (see `NUXT_GITHUB_BILLING_TOKEN` below). Keeping the two separate means metrics can keep using a fine-grained PAT or GitHub App, while only billing requires a classic PAT.\n\n\u003e [!IMPORTANT]\n\u003e **v3.0 Migration:** The new Copilot Usage Metrics API requires **Read access to members, organization copilot metrics, and organization copilot seat management** permissions. Without this, the new API endpoints will return 400/403 errors. See [GitHub App Registration](DEPLOYMENT.md#github-app-registration) for setup details.\n\nToken is not used in the frontend.\n\n````\nNUXT_GITHUB_TOKEN=\n````\n\n#### NUXT_GITHUB_BILLING_TOKEN\n\nOptional. **Dedicated classic PAT for the Billing tab and per-user AI credit spend.** When unset, the Billing tab is hidden and the \"Your AI credit spend\" card on the My Usage tab is omitted — all other features keep working.\n\nRequirements:\n- **Classic PAT only** — fine-grained PATs and GitHub Apps cannot read billing.\n- Scope: **`manage_billing:enterprise`** (or `manage_billing:copilot` for non-enterprise-owned orgs).\n- Must be **SSO-authorized** for the target enterprise if SAML SSO is enforced.\n\n````\nNUXT_GITHUB_BILLING_TOKEN=ghp_classic_pat_with_manage_billing_enterprise\n````\n\n#### NUXT_BILLING_ENTERPRISE\n\nOptional. **Forces billing calls to query `/enterprises/{slug}/...` regardless of dashboard scope.** Set to the enterprise slug when an org-scoped dashboard's org is consolidated under an enterprise (the typical case — GitHub returns 404 on the `/organizations/{org}/...` billing endpoint for those orgs).\n\n````\nNUXT_BILLING_ENTERPRISE=my-enterprise-slug\n````\n\nIf you get a 404 from the Billing tab with the dashboard scoped to an organization, the error message will point you at this variable.\n\n#### NUXT_GITHUB_API_BASE_URL\n\nOptional. Overrides the GitHub API base URL used for all server-side API calls. Set this when accessing GitHub at **GHE.com** (GitHub Enterprise Cloud with data residency), where the API is available at a dedicated subdomain.\n\n```\nNUXT_GITHUB_API_BASE_URL=https://api.SUBDOMAIN.ghe.com\n```\n\nDefaults to `https://api.github.com` when not set. Leave unset for standard GitHub.com and GitHub Enterprise Cloud (non-data-residency) deployments.\n\n\u003e [!NOTE]\n\u003e **GHES (GitHub Enterprise Server) is not supported** — the Copilot usage metrics API is not available on GHES.\n\n#### NUXT_GITHUB_APP_ID / NUXT_GITHUB_APP_PRIVATE_KEY\n\n**Alternative to PAT** — use a GitHub App installation token for backend data access. When both are set, they take priority over `NUXT_GITHUB_TOKEN`. This is the recommended credential when users authenticate via Google, Microsoft, Auth0, or Keycloak (i.e., non-GitHub identity providers), since the token is machine-issued and not tied to any individual user account.\n\nThe installation ID is **auto-discovered** from `NUXT_PUBLIC_GITHUB_ORG` — no manual configuration needed. If the App is installed on multiple orgs and no org is configured, users see an org picker after login.\n\nSee [GitHub App Installation Token](DEPLOYMENT.md#github-app-installation-token-no-pat-required) in the deployment guide for full setup instructions.\n\n```bash\nNUXT_GITHUB_APP_ID=123456\nNUXT_GITHUB_APP_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\\n...\\n-----END RSA PRIVATE KEY-----\n```\n\n#### NUXT_SESSION_PASSWORD (Required!)\n\nThis variable is required to encrypt user sessions, it needs to be at least 32 characters long.\nFor more information see [Nuxt Sessions and Authentication](https://nuxt.com/docs/guide/recipes/sessions-and-authentication#cookie-encryption-key).\n\n\u003e[!WARNING]\n\u003e This variable is required starting from version 2.0.0.\n\n#### NUXT_PUBLIC_AUTH_PROVIDERS\n\nComma-separated list of active OAuth providers: `github`, `google`, `microsoft`, `auth0`, `keycloak`. Setting this variable enables authentication — users must sign in before accessing the dashboard.\n\n```\nNUXT_PUBLIC_AUTH_PROVIDERS=github,google\n```\n\nThe corresponding `NUXT_OAUTH_\u003cPROVIDER\u003e_CLIENT_ID` and `NUXT_OAUTH_\u003cPROVIDER\u003e_CLIENT_SECRET` must also be set. See [Authentication](DEPLOYMENT.md#authentication-1) in DEPLOYMENT.md for full setup instructions per provider.\n\n#### NUXT_AUTHORIZED_USERS\n\nComma-separated list of logins or email addresses that are allowed to sign in (any provider). When empty (default), all authenticated users are allowed.\n\n```\nNUXT_AUTHORIZED_USERS=alice,bob@company.com\n```\n\n#### NUXT_AUTHORIZED_EMAIL_DOMAINS\n\nComma-separated list of email domains allowed to sign in. When empty (default), no domain restriction is applied.\n\n```\nNUXT_AUTHORIZED_EMAIL_DOMAINS=company.com\n```\n\n#### NUXT_USAGE_ADMINS\n\nComma-separated allowlist of logins or email addresses that get **administrator privileges** on the dashboard. Administrators can:\n\n* See the **Billing tab** (aggregate AI-credit breakdown by SKU/model/cost-center/repo)\n* See **all users' rows** in the User Metrics tab and Seats Analysis (per [issue #398](https://github.com/github-copilot-resources/copilot-metrics-viewer/issues/398) — restrict user-level breakdown data to authorized users for Austrian/EU compliance)\n\n```\n# Closed by default — no one is admin; non-admins see only their own row on User Metrics\nNUXT_USAGE_ADMINS=\n\n# Grant admin to specific logins/emails\nNUXT_USAGE_ADMINS=alice,bob@company.com\n```\n\n\u003e [!IMPORTANT]\n\u003e **Breaking change in 3.11.0:** `NUXT_USAGE_ADMINS` was previously *open-by-default* (an empty value meant \"everyone is admin\"). It is now **closed-by-default**: anyone not explicitly listed is treated as a regular user and can only see their own row in User Metrics + Seats. Upgrade by setting `NUXT_USAGE_ADMINS` to your admin allowlist.\n\n\u003e [!NOTE]\n\u003e When `NUXT_GITHUB_BILLING_TOKEN` is unset, the Billing tab is shown to all users (admin or not) but renders a configuration-help placeholder instead of fetching data; the `NUXT_USAGE_ADMINS` gate only applies once the token is configured.\n\nThe Billing tab exposes aggregate breakdowns (model / SKU / cost center) and an admin per-user breakdown. Per-user attribution depends on GitHub tagging each item with a `user`; some enterprise plans return only enterprise-level aggregates, in which case the per-user table is hidden behind an explanatory alert. The User Metrics `ai_credits_used` column and the My Usage spend card are independent of this.\n\n##### What non-admins see\n\n| Surface | Non-admin | Admin |\n|---|---|---|\n| Org / Enterprise aggregate metrics | ✅ all | ✅ all |\n| My Usage tab (own data) | ✅ own | ✅ own |\n| User Metrics tab | 🔒 own row only + banner | ✅ all rows |\n| Seats Analysis tab | 🔒 own seat only | ✅ all seats |\n| Billing tab (token configured) | ❌ hidden | ✅ visible |\n| Billing tab (token unset) | ⚙️ configuration-help placeholder | ⚙️ configuration-help placeholder |\n\nThe filter is enforced **server-side** — non-admin requests never receive other users' data over the wire.\n\n##### Auth-mode matrix for Billing \u0026 My Usage tabs\n\nMetrics endpoints (User Metrics, My Usage, Seats) accept any token type. Billing endpoints accept ONLY a classic PAT (which is why they have their own dedicated env var).\n\n| Feature | Mock | GitHub App | Fine-grained PAT (`NUXT_GITHUB_TOKEN`) | Classic PAT (`NUXT_GITHUB_BILLING_TOKEN`) |\n|---|---|---|---|---|\n| My Usage tab metrics | ✅ fixtures | ✅ | ✅ | ✅ |\n| User Metrics `ai_credits_used` column | ✅ fixtures | ✅ | ✅ | ✅ |\n| My Usage \"Your AI credit spend\" card | ✅ fixtures | — | — | ✅ with `manage_billing:enterprise` |\n| Billing tab (aggregate + per-user) | ✅ fixtures | — | — | ✅ with `manage_billing:enterprise` |\n\nEven when on the admin allowlist, an admin only sees billing data if `NUXT_GITHUB_BILLING_TOKEN` is set AND that classic PAT is SSO-authorized for the target enterprise. If GitHub returns 403, the tab surfaces the message inline so it's clear which side needs adjustment.\n\n#### OAuth provider variables\n\n| Variable | Provider | Description |\n|---|---|---|\n| `NUXT_OAUTH_GITHUB_CLIENT_ID` | GitHub | App client ID |\n| `NUXT_OAUTH_GITHUB_CLIENT_SECRET` | GitHub | App client secret |\n| `NUXT_OAUTH_GOOGLE_CLIENT_ID` | Google | OAuth client ID |\n| `NUXT_OAUTH_GOOGLE_CLIENT_SECRET` | Google | OAuth client secret |\n| `NUXT_OAUTH_MICROSOFT_CLIENT_ID` | Microsoft | App client ID |\n| `NUXT_OAUTH_MICROSOFT_CLIENT_SECRET` | Microsoft | App client secret |\n| `NUXT_OAUTH_MICROSOFT_TENANT` | Microsoft | Azure AD tenant ID (restricts to org) |\n| `NUXT_OAUTH_AUTH0_CLIENT_ID` | Auth0 | App client ID |\n| `NUXT_OAUTH_AUTH0_CLIENT_SECRET` | Auth0 | App client secret |\n| `NUXT_OAUTH_AUTH0_DOMAIN` | Auth0 | Tenant domain, e.g. `company.auth0.com` |\n| `NUXT_OAUTH_KEYCLOAK_CLIENT_ID` | Keycloak | Client ID |\n| `NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET` | Keycloak | Client secret |\n| `NUXT_OAUTH_KEYCLOAK_SERVER_URL` | Keycloak | Server URL |\n| `NUXT_OAUTH_KEYCLOAK_REALM` | Keycloak | Realm name |\n\n#### NUXT_PUBLIC_HIDDEN_TABS\n\nComma-separated list of dashboard tab names to hide. Applies at startup without requiring a rebuild — useful for pre-built Docker deployments. The filter is case-insensitive and trims surrounding whitespace.\n\nAvailable tab names: `languages`, `editors`, `copilot chat`, `agent activity`, `pull requests`, `github.com`, `seat analysis`, `user metrics`, `api response`\n\n````\n# Hide the \"Agent Activity\" and \"API Response\" tabs\nNUXT_PUBLIC_HIDDEN_TABS=agent activity,api response\n````\n\n#### NUXT_PUBLIC_ENABLE_HISTORICAL_MODE\n\nDefault is `false`. When set to `true`, the application uses a PostgreSQL database (configured via `DATABASE_URL`) to store and query historical Copilot metrics.\n\n\u003e [!IMPORTANT]\n\u003e The **Teams** tab is automatically hidden when `NUXT_PUBLIC_ENABLE_HISTORICAL_MODE` is not `true`. Team-level metrics are derived from per-user daily records in the database (`user_day_metrics` table). Without the database, the teams comparison tab would display identical org-wide data for every team.\n\n````\nNUXT_PUBLIC_ENABLE_HISTORICAL_MODE=false\n````\n\n#### HTTP_PROXY\n\nSolution supports HTTP Proxy settings when running in corporate environment. Simply set `HTTP_PROXY` environment variable.\n\nFor custom CA use environment variable `CUSTOM_CA_PATH` to load the certificate into proxy agent options.\n\n#### NITRO_PORT\n\nDefault is `80` in the [Dockerfile](Dockerfile). It defines the port number that Nitro (Nuxt’s server engine) will listen on.\n\nFor example, it should be set to a number between 1024 and 49151 if the application is run as a non-root user.\n\n## Install Dependencies\n\n```bash\nnpm install\n```\n\n### Compiles and Runs the Application\n\n```bash\nnpm run dev\n```\n\n### Docker Build\n\n```bash\ndocker build -t copilot-metrics-viewer .\n```\n\n### Docker Run\n\n```bash\ndocker run -p 8080:80 --env-file ./.env copilot-metrics-viewer\n```\n\nThe application will be accessible at http://localhost:8080\n\n## Health Check Endpoints\n\nFor Kubernetes deployments and health monitoring, the application provides dedicated health check endpoints that don't require authentication and don't make external API calls:\n\n- **`/api/health`** - General health check endpoint\n- **`/api/ready`** - Readiness probe endpoint \n- **`/api/live`** - Liveness probe endpoint\n\nAll endpoints return JSON responses with status information and respond in ~200ms, making them ideal for Kubernetes health checks instead of using the root `/` endpoint which triggers GitHub API calls.\n\n### Example Kubernetes Configuration\n\n```yaml\nlivenessProbe:\n  httpGet:\n    path: /api/live\n    port: 80\n  initialDelaySeconds: 30\n  periodSeconds: 10\n\nreadinessProbe:\n  httpGet:\n    path: /api/ready\n    port: 80\n  initialDelaySeconds: 5\n  periodSeconds: 5\n```\n\n## License\n\nThis project is licensed under the terms of the MIT open source license. Please refer to [MIT](./LICENSE.txt) for the full terms.\n\n## Maintainers\n\n[@martedesco](https://github.com/martedesco) \u0026 [@karpikpl](https://github.com/karpikpl)\n\n## Support\n\nThis project is independently developed and maintained, and is not an official GitHub product. It thrives through the dedicated efforts of ([@martedesco](https://github.com/martedesco)), ([@karpikpl](https://github.com/karpikpl)) and our wonderful contributors. A heartfelt thanks to all our contributors! ✨\n\nI aim to provide support through [GitHub Issues](https://github.com/github-copilot-resources/copilot-metrics-viewer/issues). While I strive to stay responsive, I can't guarantee immediate responses. For critical issues, please include \"CRITICAL\" in the title for quicker attention. 🙏🏼\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub-copilot-resources%2Fcopilot-metrics-viewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgithub-copilot-resources%2Fcopilot-metrics-viewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub-copilot-resources%2Fcopilot-metrics-viewer/lists"}