Our Jira plugin, Timesheets by Appforest, centralized time tracking at Testlify, but developers still had to stop and switch tools to log their hours by hand. The Appforest Timetracker closes that gap. It is a VS Code extension that tracks coding activity right in the editor and turns time logging into a quick action, so engineers can log to Timesheets without leaving the IDE. I owned it end to end, from concept through packaging for the Visual Studio Marketplace.
What I built
- The extension core: Built on the official VS Code Extension API. Document-change, save, and selection listeners reset an activity timestamp, checked against a 1-second poll of window focus state, to track active versus idle time quietly without interrupting the developer.
- Git-aware time logging: The extension reads the current Git branch and extracts the Jira ticket ID automatically, ensuring logged time is linked to the right issue without manual ticket search or retyping.
- Full lifecycle: Handled secure token storage via VS Code's SecretStorage API, packaging, and a manual publish to the Visual Studio Marketplace.
Why it mattered
Automating ticket matching from Git branch context eliminated manual timesheet logging steps, reduced reporting mistakes, and gave leadership cleaner data for sprint planning and client billing.
Solo, Small, Real
I'm the only contributor, 32 commits since April 2025. It's a small, personal-scale internal tool built to fix a specific daily annoyance, not a large product.
Where the Logged Time Actually Goes
The extension doesn't call Jira's REST API directly. It posts to Timesheets by Appforest's own backend, the same remote service the Forge app declares in its manifest, which then handles the Jira-facing side itself. The two projects were built to talk to each other, not to Jira independently, which is also why the Forge app's resolvers include functions specifically for clearing VS Code-sourced suggestions once they're logged.
How Activity and Ticket Detection Actually Work
Git branch detection shells out to git rev-parse --abbrev-ref HEAD directly rather than pulling in a git library, a reasonable call for reading one value instead of taking on a dependency's full API surface. The branch name is validated against /^[A-Z]+-\d+$/ before anything syncs, so a feature branch that doesn't match a ticket (like ABC-123) is silently skipped rather than logged against the wrong issue or erroring out. Activity tracking isn't per-file-switch granularity; it's a 1-second poll of window focus state alongside document-change and save listeners, with a 10-second idle threshold and a 60-second grace period before a session is considered paused. Progress persists to VS Code's globalState every second and restores on restart, with a self-healing check: if the last-synced count is somehow ahead of the tracked count on restore, a sign of a sync interrupted mid-write, it gets clamped back in line instead of drifting further out of sync.
Authentication is command-driven rather than settings-based: dedicated commands (authenticateToken, deleteToken, updateToken, syncNow, resetTime) handle the token lifecycle through input prompts, which is why there's no settings UI in the first place, a deliberate choice rather than a missing feature.
Data Model & Scale
Nothing here needs to scale beyond a single developer's own editor session: one status-bar display (ticket time and daily total), one idle/active state machine, one daily reset job at midnight. There's no case for a heavier data model at this size, and building one would be solving a problem this tool doesn't have.
Build vs. Buy
Shelling out to the git binary instead of a library like simple-git or isomorphic-git: reading one value (the current branch) doesn't justify a dependency built for full Git operations. VS Code's own SecretStorage API instead of a custom encrypted-file token store: the platform already solves secure credential storage for exactly this case.
Stack
VS Code Extension API, TypeScript, Node's built-in child_process for Git access, VS Code's SecretStorage API for token storage, published on the Visual Studio Marketplace.