ShellTime

Track your coding time and productivity across projects with ShellTime. Automatic language detection, project analytics, and detailed activity insights.
Features
- Automatic Time Tracking - Tracks your coding activity in the background without interrupting your workflow. Reading, scrolling and navigating code counts too, not just typing
- Notebooks - Cells of Jupyter and other notebooks count toward the notebook file
- Language Detection - Automatically detects and categorizes time by programming language
- Project Analytics - See time spent per project and workspace on your ShellTime dashboard
- Git Integration - Tracks activity by git branch
- Debug Session Awareness - Distinguishes between coding and debugging time
- Today's Activity - Open your ShellTime activity page straight from VS Code
- CLI Update Notice - Tells you when a newer ShellTime CLI is available
Prerequisites
The extension needs VS Code 1.107 or later and the ShellTime daemon running on the same machine.
1. Install ShellTime CLI
curl -sSL https://shelltime.xyz/i | bash
Or with Homebrew (macOS only):
brew install shelltime/tap/shelltime
After installation, reload your shell configuration:
- zsh:
source ~/.zshrc
- fish:
source ~/.config/fish/config.fish
- bash:
source ~/.bashrc
2. Initialize and Authenticate
shelltime init
This will:
- Open your browser to authenticate with your ShellTime account
- Install shell hooks for your shell (zsh/fish/bash)
- Install and start the ShellTime daemon
3. Enable Code Tracking
The daemon only accepts editor activity when code tracking is enabled. Configs created by recent versions of shelltime init already have it. Otherwise, add the following to your ShellTime config (~/.shelltime/config.yaml). Recent daemons pick the change up right away; older ones need a restart (shelltime daemon reinstall):
codeTracking:
enabled: true
Or in TOML format (~/.shelltime/config.toml):
[codeTracking]
enabled = true
Config file
The extension reads the same files as the ShellTime CLI: the first of ~/.shelltime/config.yaml, config.yml and config.toml, with the first config.local.yaml, config.local.yml or config.local.toml merged over it. The extension watches them, so changes apply without reloading VS Code. To use another file, set shelltime.configPath; a shelltime.configPath that names one of the files above still gets config.local.* merged over it. If there is no config file, the extension uses its VS Code settings.
Extension Settings
This extension contributes the following settings:
shelltime.configPath: Path to a ShellTime config file (.yaml, .yml or .toml). Leave it empty to read the CLI's files (see Config file). Its codeTracking.enabled and socketPath values take precedence over the VS Code settings below (default: empty)
shelltime.heartbeatInterval: Interval in milliseconds between heartbeat flushes, minimum 30000 (default: 120000)
shelltime.debug: Enable debug logging in the console (default: false)
shelltime.enabled: Deprecated, use codeTracking.enabled in your ShellTime config instead. Enable/disable ShellTime tracking (default: true)
shelltime.socketPath: Deprecated, use socketPath in your ShellTime config instead. Path to the ShellTime daemon socket (default: /tmp/shelltime.sock)
Commands
ShellTime: Show Status - Display the daemon's version, uptime and platform, or offer to retry the connection if it isn't running
ShellTime: Flush Heartbeats - Manually flush pending heartbeats to the daemon
ShellTime: Today - Open your activity page on ShellTime in the browser (the webEndpoint from your config, https://shelltime.xyz by default). Needs the daemon running and you signed in
How It Works
The extension monitors your VS Code activity and sends heartbeats to a local daemon:
- Event Monitoring - Tracks edits, saves, switching files, scrolling and cursor movements, so reading and reviewing code keeps your session going. Everything that happens while the VS Code window is in the background is ignored, as are changes that leave a file unmodified (a file reloaded after
git checkout or a formatter run outside VS Code) and repeated events with an unchanged cursor. Only files on disk and the cells of notebooks on disk are tracked (not untitled notebooks or interactive windows), and files inside .git are skipped
- Debouncing - Batches events to reduce overhead (max 1 heartbeat per file per 30 seconds). Saves you make send one every time; auto-saves count like edits, in notebooks too
- Periodic Flush - Sends collected heartbeats to the daemon every 2 minutes, at most 500 per message (change the interval with
shelltime.heartbeatInterval)
- Offline Support - Keeps heartbeats queued while the daemon is unreachable or has code tracking turned off, and retries them on the next flush (up to 5,000, oldest dropped first)
- Flush on Exit - Sends anything still queued when VS Code closes or tracking is turned off. What the daemon can't take then goes to
~/.shelltime/coding-heartbeat.data.log, which the daemon resends once it runs
The project is the workspace folder the file belongs to, or the git repository around it; the branch is read from the repository's HEAD (for a repository that uses git's reftable format, from git itself, at most once a minute).
On startup, if your config has apiEndpoint and webEndpoint, the extension also checks whether your ShellTime CLI is up to date and, if not, offers to copy the update command.
Status Bar
The extension shows its status in the VS Code status bar:
$(pulse) ShellTime - Connected and tracking (hover to see how many heartbeats are pending)
$(circle-slash) ShellTime - The daemon runs but has code tracking turned off in its config (heartbeats queued)
$(debug-disconnect) ShellTime - Daemon not running (heartbeats queued). In a remote window (SSH, WSL, Dev Containers) the extension runs on the remote host, which needs a ShellTime daemon of its own
Click the status bar item to view daemon status.
Privacy
The extension sends heartbeats only to the local ShellTime daemon via Unix socket. A heartbeat contains metadata such as the file path, project, language, git branch, line count, cursor position, and editor, OS and machine names, never file contents. The daemon syncs your coding activity to the ShellTime server for analytics and cross-device access. The only network request the extension makes itself is the CLI version check against your configured apiEndpoint.
License
See LICENSE for details.