A Neovim plugin for automatic collection and analysis of GitHub repository traffic statistics.
- Features
- Requirements
- Installation
- Configuration
- Usage
- Dashboard UI
- Documentation
- Troubleshooting
- Performance
- Cross-Platform Support
- License
- Contributing
- Support
- Automatic Data Collection: Daily fetching of clones, views, referrers, and paths
- Historical Storage: All data stored locally as JSON with configurable paths
- Flexible Configuration: Setup via
setup()orconfig.json, with custom storage paths - Detailed Analytics: Time-range queries, aggregations, and period comparisons
- Async-First: Non-blocking API calls via
vim.system - Visualizations: ASCII sparklines and comparison charts
- Export Capabilities: CSV and Markdown format support
- Period Comparison: Diff mode for trend analysis (month-over-month, year-over-year)
- Smart Defaults: Optional date parameters with intelligent fallbacks
- Floating Windows: Clean, formatted result displays
- Cross-Platform: Windows, macOS, Linux support
- Autocompletion: All commands support Tab completion
- Neovim ≥ 0.9.0
- curl (for API requests)
- GitHub Personal Access Token with
repopermission
- Visit: https://github.com/settings/tokens
- Click "Generate new token (classic)"
- Select
reposcope - Generate and save token securely
{
"StefanBartl/github_stats.nvim",
config = function()
require("github_stats").setup({
repos = { "user/repo1", "user/repo2" },
})
end,
}use {
"StefanBartl/github_stats.nvim",
config = function()
require("github_stats").setup({
repos = { "user/repo1", "user/repo2" },
})
end,
}The plugin supports two configuration methods:
require("github_stats").setup({
repos = { "username/repo1", "username/repo2" },
token_source = "env",
token_env_var = "GITHUB_TOKEN",
fetch_interval_hours = 24,
notification_level = "all",
})Quick Setup:
-- Minimal configuration
require("github_stats").setup({
repos = { "username/repo" },
})Create ~/.config/nvim/github-stats/config.json:
{
"repos": ["username/repo1", "username/repo2"],
"token_source": "env",
"token_env_var": "GITHUB_TOKEN",
"fetch_interval_hours": 24,
"notification_level": "all"
}Then in your Neovim config:
require("github_stats").setup() -- Reads from config.jsonWhy use config.json?
If you sync your Neovim configuration across multiple systems (via Git/dotfiles), storing the plugin configuration and data in stdpath('config')/github-stats/ allows you to:
- Share the same historical data across all systems
- Maintain consistent repository lists
- Backup everything in one place
See docs/configuration/INTRO.md for detailed configuration guide.
Option A: Environment Variable (Recommended)
# In ~/.bashrc, ~/.zshrc, etc.
export GITHUB_TOKEN="ghp_your_token_here"Option B: Token File
echo "ghp_your_token_here" > ~/.github_token
chmod 600 ~/.github_tokenThen in setup:
require("github_stats").setup({
repos = { "username/repo" },
token_source = "file",
token_file = "~/.github_token",
})aarequire("github_stats").setup({
repos = { "username/repo" },
config_dir = "~/my-github-stats", -- Custom config location
data_dir = "/mnt/shared/github-data", -- Custom data storage (e.g., NAS)
})" Respects configured interval (default: 24h)
:GithubStatsFetch
" Force immediate fetch
:GithubStatsFetch forceAutocompletion: force
" All available data (smart defaults)
:GithubStatsShow username/repo clones
:GithubStatsShow username/repo views
" With date range filter
:GithubStatsShow username/repo clones 2025-01-01 2025-12-31
" Only start date (end defaults to today)
:GithubStatsShow username/repo views 2025-01-01Smart Defaults:
- No
start_date→ Shows all available data - No
end_date→ Defaults to today - Plugin notifies about applied defaults
Autocompletion: Repository names, metrics (clones, views)
:GithubStatsSummary clones
:GithubStatsSummary viewsShows aggregated statistics for all configured repositories.
Autocompletion: Metrics
" Top 10 (default)
:GithubStatsReferrers username/repo
" Top 20
:GithubStatsReferrers username/repo 20Autocompletion: Repository names
" Top 10 (default)
:GithubStatsPaths username/repo
" Top 20
:GithubStatsPaths username/repo 20Autocompletion: Repository names
" Sparkline chart for single metric
:GithubStatsChart username/repo clones
" Comparison chart (count vs uniques)
:GithubStatsChart username/repo both
" With date range (smart defaults apply)
:GithubStatsChart username/repo views 2025-01-01Example Output:
GitHub Stats: username/repo/clones
────────────────────────────────────────────────────────────────
▂▃▅▇█▇▅▃▂▁▂▃▅▇█▇▅▃▂▁▂▃▅▇█▇▅▃▂▁▂▃▅▇█▇▅▃▂▁▂▃▅▇█▇▅▃▂▁▂▃▅▇█▇▅▃▂▁
Period: 2025-11-20 to 2025-12-20 (30 days)
Max: 1,234 | Avg: 567 | Min: 123 | Total: 17,010
Autocompletion: Repository names, metrics
" Export single repo to CSV
:GithubStatsExport username/repo clones ~/data.csv
" Export single repo to Markdown
:GithubStatsExport username/repo views ~/report.md
" Export all repos to Markdown summary
:GithubStatsExport all clones ~/summary.mdSupported Formats:
.csv– Single repository only, daily breakdown.md– Single repository or all repositories with summary
Autocompletion: Repository names, metrics, file paths
" Compare two months
:GithubStatsDiff username/repo clones 2025-01 2025-02
" Compare two years
:GithubStatsDiff username/repo views 2024 2025Example Output:
Period Comparison: username/repo - clones
══════════════════════════════════════════════════════════════════
Period 1: 2025-01
Total Count: 1,234
Total Uniques: 567
Days: 31
Avg/Day: 39 count, 18 uniques
Period 2: 2025-02
Total Count: 1,423
Total Uniques: 645
Days: 28
Avg/Day: 50 count, 23 uniques
Changes:
──────────────────────────────────────────────────────────────────
Count: +15.3%
Uniques: +13.8%
Autocompletion: Repository names, metrics, period suggestions
:GithubStatsDebugShows:
- Configuration status
- Token availability
- Last fetch summary with detailed error information
- Test API call for first repository
Interactive TUI dashboard for monitoring all repositories at a glance:
" Open dashboard
:GithubStatsDashboard
" Open with forced refresh
:GithubStatsDashboard!Features:
- Real-time overview of all configured repositories
- Visual trend indicators with sparklines
- Keyboard-driven navigation (j/k)
- Interactive sorting (by clones, views, name, trend)
- Configurable time ranges (7d, 30d, 90d, all)
- Auto-refresh capabilities
- Drill-down to detailed statistics
Key Bindings:
| Key | Action |
|---|---|
j / <Down> |
Navigate down |
k / <Up> |
Navigate up |
<Enter> |
Show detailed view |
r |
Refresh selected repository |
R |
Refresh all repositories |
s |
Cycle sort order |
t |
Cycle time range |
? |
Show help |
q / <Esc> |
Quit dashboard |
Configuration:
require("github_stats").setup({
repos = { ... },
dashboard = {
enabled = true,
auto_open = false, -- Open on VimEnter
refresh_interval_seconds = 300, -- 5 minutes (0 = disabled)
sort_by = "clones", -- Default sort
time_range = "30d", -- Default time range
keybindings = {
-- Customize keybindings
navigate_down = "j",
navigate_up = "k",
show_details = "",
-- ... more bindings
},
},
})Auto-Open on Startup:
require("github_stats").setup({
dashboard = {
enabled = true,
auto_open = true, -- Dashboard opens automatically
},
})See also: Dashboard Guide
Use predefined shortcuts instead of typing full ISO dates:
" Built-in presets
:GithubStatsShow username/repo clones last_month
:GithubStatsChart username/repo views this_quarter
:GithubStatsDiff username/repo clones last_week this_week
" Custom presets (after configuration)
:GithubStatsShow username/repo clones fiscal_year
:GithubStatsChart username/repo both current_sprintAvailable Built-in Presets:
today,yesterdaylast_week,last_month,last_quarter,last_yearthis_week,this_month,this_quarter,this_year
Create Custom Presets:
-- In init.lua after setup()
local config = require("github_stats.config").get()
-- Example: Fiscal Year (April 1 - March 31)
config.date_presets.custom.fiscal_year = function()
local now = os.date("*t")
local fy_year = now.month >= 4 and now.year or now.year - 1
return string.format("%04d-04-01", fy_year), string.format("%04d-03-31", fy_year + 1)
end
-- Example: Current 2-week Sprint
config.date_presets.custom.current_sprint = function()
local now = os.time()
local sprint_length = 14 * 86400
local date_info = os.date("*t", now)
local days_since_monday = (date_info.wday == 1) and 6 or (date_info.wday - 2)
local monday = now - (days_since_monday * 86400)
local sprint_start = monday - (monday % sprint_length)
return os.date("%Y-%m-%d", sprint_start), os.date("%Y-%m-%d", sprint_start + sprint_length - 86400)
endAutocompletion: Tab-completion shows all available presets when typing date parameters.
See also: Custom Date Presets Guide
:checkhealth github_statsPerforms comprehensive diagnostics:
- Configuration validity
- Token access and permissions
- curl availability (cross-platform detection)
- Storage path accessibility
- API connectivity test (with timeout protection)
- Configuration Guide – Detailed setup instructions
- User Commands – Complete command reference
- Troubleshooting Guide – Common issues and solutions
:checkhealth github_stats
:GithubStatsDebug
:messagesRun :GithubStatsDebug to see detailed error information for each failed repository/metric combination.
Common causes:
404 Not Found– Repository name incorrect or deleted403 Forbidden– Token lacks permissions or rate limit exceeded401 Unauthorized– Invalid or expired token
export GITHUB_TOKEN="ghp_your_token_here"Then restart Neovim.
Possible causes:
- Repository name in configuration doesn't match exactly
- No data fetched yet – run
:GithubStatsFetch force - Token lacks access to repository
Requires Neovim ≥ 0.9.0. Run :checkhealth github_stats to verify.
See docs/TROUBLESHOOTING.md for comprehensive troubleshooting guide.
- Storage: JSON-based, ~2KB per data point
- Fetch Time: ~1-2 seconds per repository (parallel execution)
- UI Blocking: None (fully async via
vim.system) - Memory: Minimal (only active data in RAM)
- Rate Limits: 5,000 requests/hour with token
Capacity: With daily fetching (4 requests/repo), the plugin can handle ~1,250 repositories.
- curl detection via PowerShell's
Get-Command - File paths automatically normalized
- Environment variables:
$env:GITHUB_TOKENin PowerShell
- Standard curl detection via
command -v - POSIX-compliant paths
- Environment variables: Standard bash/zsh export
| Platform | Default Config Path |
|---|---|
| Linux | ~/.config/nvim/github-stats/ |
| macOS | ~/.config/nvim/github-stats/ |
| Windows | %LOCALAPPDATA%\nvim\github-stats\ |
Custom paths can be specified via config_dir and data_dir options.
~/.config/nvim/github-stats/
├── config.json # User configuration (optional)
├── last_fetch.json # Interval tracking
└── data/
└── username_repo/
├── clones/
│ ├── 2025-12-20T10-30-00.json
│ └── 2025-12-21T10-30-00.json
├── views/
├── referrers/
└── paths/
The plugin uses GitHub REST API v3:
GET /repos/{owner}/{repo}/traffic/clones– Clone statisticsGET /repos/{owner}/{repo}/traffic/views– View statisticsGET /repos/{owner}/{repo}/traffic/popular/referrers– Top referrersGET /repos/{owner}/{repo}/traffic/popular/paths– Top paths
Pull requests are welcome. For major changes, please open an issue first to discuss proposed changes.
ℹ️ This plugin is under active development – some features are planned or experimental. Expect changes in upcoming releases.
Your feedback is very welcome!
Please use the GitHub issue tracker to:
- Report bugs
- Suggest new features
- Ask questions about usage
- Share thoughts on UI or functionality
For general discussion, feel free to open a GitHub Discussion.
If you find this plugin helpful, consider giving it a ⭐ on GitHub — it helps others discover the project.