Skip to content

SiiahK/focusd.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 

Repository files navigation

focusd.nvim

Passive coding telemetry for Neovim. You code, your habits update themselves — zero check-ins, zero keystroke overhead, zero cloud.

The editor client for focusd, the local-first focus engine. It talks raw HTTP over the daemon's unix socket through libuv (vim.uv): no curl forks, no threads, and Neovim's single-threaded main loop never waits on anything.

Requirements

  • Neovim >= 0.10

  • the focusd daemon binary:

    go install github.com/SiiahK/focusd@latest

    or grab a prebuilt one from the releases page. The plugin autostarts the daemon when it isn't running (safe by design: the daemon is a flock singleton).

Install

lazy.nvim

{
  "SiiahK/focusd.nvim",
  event = "VeryLazy",
  opts = {},
}

packer.nvim

use({
  "SiiahK/focusd.nvim",
  config = function()
    require("focusd").setup()
  end,
})

Configuration (defaults)

require("focusd").setup({
  sock = nil,                 -- unix socket path; nil = auto-discovery
                              -- (FOCUSD_SOCK → XDG_RUNTIME_DIR → OS cache dir)
  bin = "focusd",             -- daemon binary for autostart (found in PATH)
  autostart = true,           -- start the daemon when the socket doesn't answer
  timeout_ms = 250,           -- hard cap: the editor NEVER waits longer than this
  flush_interval_ms = 15000,  -- heartbeat batch cadence (saves flush immediately)
  status_interval_ms = 5000,  -- statusline cache refresh
  max_backoff_ms = 30000,     -- exponential backoff ceiling while daemon is down
})

Statusline

require("focusd").status() is a pure memory read — call it on every redraw for free. An async 5s poll fills the cache and pauses when Neovim loses OS focus.

-- lualine
sections = { lualine_x = { require("focusd").status } }

Commands

Command Effect
:FocusdStatus show the current focus state
:FocusdFocusStart {id} start a focus session for a habit
:FocusdFocusStop stop the active session and log it
:FocusdFlush send pending heartbeats now
:checkhealth focusd socket, binary and a real daemon round-trip

How it works

Autocmds on the typing path (TextChanged, BufEnter, BufWritePost, …) do O(1) in-memory counter bumps only. A timer flushes the accumulated activity every 15s — immediately on save — as one coalesced batch to POST /heartbeat. Every request carries a hard 250ms timeout, requests of the same class cancel their stale predecessor ("latest wins"), and when the daemon is down the plugin backs off exponentially and degrades silently: your editor never lags, telemetry at worst loses its last interval.

Your data lands in a local SQLite file owned by the daemon. See where the week went:

focusd report

License

MIT

About

Passive coding telemetry for Neovim — the editor client for the focusd local-first focus engine

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages