{"id":25059598,"url":"https://github.com/lnus/stalker.nvim","last_synced_at":"2026-02-19T12:02:04.174Z","repository":{"id":276042170,"uuid":"925888775","full_name":"lnus/stalker.nvim","owner":"lnus","description":"Statistics for NeoVim usage","archived":false,"fork":false,"pushed_at":"2025-02-10T23:42:37.000Z","size":46,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-05T00:44:12.334Z","etag":null,"topics":["neovim","neovim-plugin","nvim"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/lnus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-02T01:30:34.000Z","updated_at":"2025-02-15T08:50:30.000Z","dependencies_parsed_at":"2025-04-14T14:07:30.215Z","dependency_job_id":null,"html_url":"https://github.com/lnus/stalker.nvim","commit_stats":null,"previous_names":["lnus/stalker.nvim"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lnus/stalker.nvim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lnus%2Fstalker.nvim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lnus%2Fstalker.nvim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lnus%2Fstalker.nvim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lnus%2Fstalker.nvim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lnus","download_url":"https://codeload.github.com/lnus/stalker.nvim/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lnus%2Fstalker.nvim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29612509,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T10:52:55.328Z","status":"ssl_error","status_checked_at":"2026-02-19T10:52:26.323Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["neovim","neovim-plugin","nvim"],"created_at":"2025-02-06T15:35:36.578Z","updated_at":"2026-02-19T12:02:04.155Z","avatar_url":"https://github.com/lnus.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align='center'\u003e\n    \u003cimg src='https://c.tenor.com/3MEoufxx7vIAAAAC/tenor.gif' width='200px'/\u003e\n\u003c/p\u003e\n\n\u003ch1 align='center'\u003e\n    stalker.nvim\n\u003c/h1\u003e\n\n\u003cp align='center'\u003e\n    Statistics for NeoVim usage\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n    \u003ca href=\"https://github.com/neovim/neovim/releases/v0.9.0\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Neovim-0.9.0-blueviolet.svg?style=flat-square\u0026logo=Neovim\u0026logoColor=white\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/lnus/stalker.nvim/blob/main/LICENSE\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/license/lnus/stalker.nvim?style=flat-square\"/\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n    \u003cstrong\u003e\n        ⚠️ This is very much a work in progress ⚠️ \n    \u003c/strong\u003e\n\u003c/p\u003e\n\u003cp align='center'\u003e\n    \u003cstrong\u003e\n        ⚠️ Breaking changes WILL be pushed to main ⚠️ \n    \u003c/strong\u003e\n\u003c/p\u003e\n\n\u003c!-- TODO: Add usage gif or something --\u003e\n\n## Features\n\n- Live tracking for mode switching\n- Live tracking for (some) motions\n- Store usage statistics to disk\n- Send periodic sync data to a web endpoint\n- Send realtime data to a web endpoint\n\n### Tracked data\n\n\u003c!-- TODO: Clean up --\u003e\n\n```\nnav = { 'h', 'j', 'k', 'l' },\nword = { 'w', 'b', 'e', 'ge' },\nscroll = { '\u003cC-d\u003e', '\u003cC-u\u003e', '\u003cC-f\u003e', '\u003cC-b\u003e' },\nfind = { 'f', 'F', 't', 'T' },\nsearch = { '*', '#', 'n', 'N' },\nparagraph = { '{', '}' },\nline = { '0', '$', '^', 'g_' },\nindent = { '\u003e', '\u003c', '=', '\u003e\u003e', '\u003c\u003c' },\njumps = { 'gi', 'gv', '\u003cC-o\u003e', '\u003cC-i\u003e', 'g;', 'g,' },\n```\n\n## Usage\n\nSession tracking should start as soon as NeoVim starts,\nalong with local storage syncing as well as the\nweb sync endpoint.\n\nAvailable commands:\n\n- `:Stalker` - Show current session statistics\n- `:StalkerTotals` - Show total statistics\n- `:StalkerResetSync` - Reset web sync state after failures\n- `:StalkerResetRlSync` - Reset live sync state after failure\n\n### Troubleshooting\n\n- If web sync fails, use `:StalkerResetSync` to reset the sync state\n- If live sync fails, use `:StalkerResetRlSync` to reset the sync state\n- Check `:messages` for debug output when `verbose = true`\n\n## TODO: Requirements\n\n- NeoVim \u003e= v0.9.0 (I need to double check this)\n- cURL, I guess. For some things.\n\n## Installation\n\n### lazy.nvim\n\n```lua\n{\n    'lnus/stalker.nvim',\n    opts = {} -- config goes here\n},\n```\n\nAlternatively\n\n```lua\n{\n    'lnus/stalker.nvim',\n    config = function()\n        require('stalker').setup {} -- config goes here\n    end,\n},\n```\n\n## Configuration\n\nThese options can all be passed through `opts` if using [lazy.nvim](https://github.com/folke/lazy.nvim)\n\n```lua\nrequire('stalker').setup{\n    -- These are the default config values\n    verbose = false, -- Enable debug logging\n\n    -- Storage (Will probably be moved into sub-table)\n    store_locally = true, -- Should save stats to file\n    sync_interval = 30, -- Interval for saving to file/send to endpoint\n    sync_endpoint = nil, -- Optional web sync endpoint\n\n    -- Enable or disable specific tracking options\n    tracking = {\n        motions = true,\n        modes = true,\n    },\n\n    -- Realtime\n    realtime = {\n        enabled = false, -- What it says on the tin\n        sync_endpoint = nil, -- Realtime sync endpoint\n        sync_delay = 200, -- How often to flush\u0026\u0026send buffer in ms\n        max_buffer_size = 10, -- Force flush\u0026\u0026send buffer if this big\n    },\n}\n```\n\n## Data\n\n### Local storage\n\nLocal data will be stored within `vim.fn.stdpath 'data'`\nin the `stalker` directory.\n\nSession stats and the total of all session stats will be\nstored in the `json` format.\n\n### Realtime web endpoint\n\nTo set up realtime data syncing, structure config like this:\n\n```lua\nrequire('stalker').setup {\n    realtime = {\n        enabled = true,\n        sync_endpoint = 'http://localhost:8000/live',\n        headers = {\n            Authorization = 'Secret-Token',\n        },\n    },\n}\n```\n\n#### Example consumer endpoint (FastAPI)\n\n```python\n@app.post(\"/live\")\nasync def receive_live(request: Request):\n    # Read the raw body data and decode to string\n    raw_data = await request.body()\n    data_str = raw_data.decode(\"utf-8\", errors=\"replace\").strip()\n\n    # Split the events by delim (newline)\n    events = data_str.split(\"\\n\") if data_str else []\n\n    print(\"\\n=== Stalker Update ===\")\n    print(f\"Received {len(events)} ({len(raw_data)} bytes) event(s):\")\n    for event in events:\n        print(f\"Event: {event}\")\n    print(\"======================\\n\")\n\n    return {\"status\": \"ok\"}\n```\n\n### Periodic web endpoint\n\n\u003e Note to self: Add config to pass additional headers, for auth etc.\n\nTo set up periodic data syncing, structure config like this:\n\n```lua\nrequire('stalker').setup {\n    sync_endpoint = 'WEB_ENDPOINT'\n}\n```\n\n#### Example consumer endpoint (FastAPI)\n\n```python\n@app.post(\"/stalker\")\nasync def receive_stats(request: Request):\n    data = await request.json()\n    timestamp = datetime.fromtimestamp(data[\"timestamp\"])\n\n    print(\"\\n=== Stalker Update ===\")\n    print(f\"Time: {timestamp}\")\n    print(f\"Event: {data['event_type']}\")\n    print(\"Stats:\")\n    print(json.dumps(data[\"stats\"], indent=2))\n    print(\"===================\\n\")\n\n    return {\"status\": \"ok\"}\n```\n\n## TODO\n\n- [ ] feat: Add tracking for all modes\n- [ ] feat: Add config for custom tracking\n- [ ] feat: Add optional command tracking\n  - This could expose data, so:\n    - Make it off by default\n    - Track only base command?\n- [ ] feat: Add event types, and send those as well\n  - Change event: Mode changes (Instead of sending n_to_i)\n  - Motion event: Motion keys (Currently only event)\n  - BufEnter event: When entering a buffer, send filetype?\n  - VimEnter/Session start event (just send on plugin init)\n  - VimLeave/Session end event (I already autocmd this)\n- [ ] perf: Double check the perf of event buffer\n  - I feel like just posting to an endpoint over and over isn't... great.\n  - If event buffer feels nice to use,\n    we can use that for persitent data too, rather than a periodic timer.\n    So everything registers as an event and then we match over config to\n    decide if to write to file, send realtime data or big sync to endpoint.\n- [ ] refactor: Update file structure of repo\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flnus%2Fstalker.nvim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flnus%2Fstalker.nvim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flnus%2Fstalker.nvim/lists"}