RepoPilotOpen in app →

Planshit/Tai

👻 在Windows上统计软件使用时长和网站浏览时长

Mixed

Slowing — last commit 11mo ago

worst of 4 axes
Use as dependencyMixed

no tests detected; no CI workflows detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isMixed

last commit was 11mo ago; no CI workflows detected

  • Last commit 11mo ago
  • 8 active contributors
  • MIT licensed
Show 4 more →
  • Slowing — last commit 11mo ago
  • Single-maintainer risk — top contributor 88% of recent commits
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: add a test suite
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/planshit/tai?axis=fork)](https://repopilot.app/r/planshit/tai)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/planshit/tai on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: Planshit/Tai

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Planshit/Tai shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Slowing — last commit 11mo ago

  • Last commit 11mo ago
  • 8 active contributors
  • MIT licensed
  • ⚠ Slowing — last commit 11mo ago
  • ⚠ Single-maintainer risk — top contributor 88% of recent commits
  • ⚠ No CI workflows detected
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live Planshit/Tai repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/Planshit/Tai.

What it runs against: a local clone of Planshit/Tai — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in Planshit/Tai | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | Last commit ≤ 354 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>Planshit/Tai</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Planshit/Tai. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/Planshit/Tai.git
#   cd Tai
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of Planshit/Tai and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Planshit/Tai(\\.git)?\\b" \\
  && ok "origin remote is Planshit/Tai" \\
  || miss "origin remote is not Planshit/Tai (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 354 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~324d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Planshit/Tai"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Tai is a Windows system monitor (C# .NET Framework 4.8) that tracks application usage duration and website browsing time in real-time, storing statistics in a local SQLite database. It captures active window foreground events via Win32 API hooks, integrates with browsers through WebSocket extensions for URL tracking, and provides detailed daily/hourly breakdowns with optional auto-categorization and process association. Monolithic WinForms desktop app: Core/ contains the business logic organized by concern (Enums/ for type definitions, Librarys/ for utilities like ProcessHelper, SQLite wrappers, Logger), Models/ for data structures (AppObserver for window tracking, Config for settings, Db for persistence). Event/ folder handles pub-sub patterns (AppObserverEventHandler, BrowserObserverEventHandler). No separation of UI layer visible in provided file list.

👥Who it's for

Windows power users, productivity analysts, and managers who need visibility into how employees or teams spend time across applications and websites; also suited for individuals performing time audits of their own work patterns and leisure usage.

🌱Maturity & risk

Actively developed with a mature feature set (v1.x releases available, comprehensive README with multi-language support). However, no visible CI/CD pipeline, automated tests, or issue tracker data provided in the file listing. Single-maintainer project (Planshit) with evidence of recent work on browser extensions and data export features.

Requires administrator privileges for full functionality (Win32 API window hooking), which is a security/privilege requirement. No visible test coverage in file structure. Dependency on .NET Framework 4.8 creates Windows-specific lock-in. Browser extension integration points (WebSocket in Core/Librarys/Browser/WebSocketEvent.cs) add complexity but appear non-critical to core app function.

Active areas of work

Based on README: active work on browser extension support (instructions at discussions/279), auto-categorization by directory matching, sleep/idle detection refinement, and data export to .xlsx/.csv formats. Recent focus appears to be on expanding browser coverage (multiple BrowserType.cs entries) and improving the WebSocket integration for real-time site tracking.

🚀Get running

Clone: git clone https://github.com/Planshit/Tai.git. Open Core/Core.csproj in Visual Studio (requires .NET Framework 4.8 SDK). Restore NuGet packages. Build in Release mode. Run the resulting executable in bin/Release/ with administrator privileges. No npm/package manager involved—pure C# .NET project.

Daily commands: After build: execute bin/Release/👻Tai.exe with admin rights. Runs as system tray application; double-click tray icon to open UI, right-click for menu. Data persisted to <install-dir>/Data/data.db. Browser extension requires separate installation and enablement in Settings > 常规 > 功能.

🗺️Map of the codebase

🛠️How to make changes

New tracking rules: edit Core/Models/AppObserver/AppInfo.cs and ProcessHelper.cs. New browser support: extend Core/Enums/BrowserType.cs and Core/Librarys/Browser/. Database schema changes: Core/Librarys/SQLite/TaiDbContext.cs. Config options: Core/Models/Config/ (add to appropriate *Model.cs). Event handling: add handler to Core/Event/. Filtering/categorization logic: Core/Models/CategoryModel.cs and regex in RegexHelper.cs.

🪤Traps & gotchas

Requires administrator privileges to hook foreground window events—testing/development must run as admin. Win32 API calls are synchronous and run on the main thread; blocking here will freeze the UI. Browser extension integration uses WebSocket on a local port; ensure no port conflicts with Dev Tools or other services. SQLite database file location is hardcoded relative to executable directory (Data/data.db); moving the executable without the Data folder will lose all historical data. No connection pooling visible in SQLiteBuilder.cs—high-frequency DB writes during peak usage may cause lock contention.

💡Concepts to learn

  • Win32 Window Hooks / SetWinEventHook — Tai's core tracking mechanism relies on OS-level hooks to detect foreground window changes without polling; understanding this is critical to modifying app detection logic
  • Process Handle and Window Handle Mapping — The system must map Win32 window handles to process IDs and executable paths; ProcessHelper.cs encapsulates this; mishandling crashes the tracker
  • SQLite Database Context / ORM Pattern — Data persistence uses a custom SQLite wrapper (TaiDbContext); new schema changes or query optimizations require understanding the ORM approach and n+1 query risks
  • Observer / Pub-Sub Event Pattern — Core/Event/ implements event handlers (AppObserverEventHandler, BrowserObserverEventHandler) for decoupled communication; adding new event types requires understanding this pattern
  • WebSocket Server for Browser Extension Communication — Browser extensions push URL data via WebSocket to the desktop app; understanding the message format and lifecycle is needed to add new browser support or extend tracking
  • Idle/Sleep Detection via Win32 GetLastInputInfo — Core/Enums/SleepStatus.cs and SleepStatus detection prevent inflating usage time when the user is away; affects time accounting accuracy
  • Regular Expression Filtering and URL Parsing — App/site filtering and categorization rely on regex patterns and UrlHelper.cs for domain extraction; buggy patterns cause false positives in tracking or filtering
  • ActivityWatch/activitywatch — Cross-platform time tracking with similar foreground-window monitoring, but open-source and supports macOS/Linux; reference for event-driven architecture
  • RescueTime/rescuetime — Proprietary Windows app solving the same productivity tracking problem; Tai is the open-source alternative
  • slenderestman/RapidCopy — Another C# Win32 desktop utility demonstrating modern Windows tray app patterns and P/Invoke usage
  • Planshit/Tai-extension-browser — The companion browser extension repository for website tracking; essential for Tai's web browsing feature

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add unit tests for Core/Librarys/SQLite/SQLiteBuilder.cs and TaiDbContext.cs

The SQLite database layer is critical for persisting all app/web usage statistics, but there are no visible test files in the repo. Adding tests for SQLiteBuilder query generation and TaiDbContext CRUD operations would prevent regressions when modifying database schemas and ensure data integrity across app updates.

  • [ ] Create Core.Tests project with xUnit/NUnit framework
  • [ ] Write tests for SQLiteBuilder.cs covering SELECT, INSERT, UPDATE, DELETE query generation
  • [ ] Write integration tests for TaiDbContext.cs with in-memory SQLite database
  • [ ] Test data models: WebBrowseLogModel, WebSiteModel, WebUrlModel, WebSiteCategoryModel persistence
  • [ ] Ensure tests cover edge cases like concurrent writes from AppObserver and BrowserObserver

Refactor Win32API.cs and ProcessHelper.cs into focused utility modules

Core/Librarys/Win32API.cs likely contains multiple unrelated Windows interop concerns (window detection, process querying, sleep status monitoring). Splitting this into focused files (WindowInterop.cs, ProcessInterop.cs, SystemInterop.cs) would improve maintainability and make it easier for contributors to locate and understand specific functionality used by AppObserver.cs and DateTimeObserver.cs.

  • [ ] Analyze Win32API.cs to identify distinct responsibility groups (window management, process enumeration, system status)
  • [ ] Create separate files: Core/Librarys/Win32Interop/WindowInterop.cs, ProcessInterop.cs, SystemInterop.cs
  • [ ] Move related methods and P/Invoke declarations to appropriate files
  • [ ] Update usages in Core/Servicers/Instances/AppObserver.cs and DateTimeObserver.cs
  • [ ] Add XML documentation comments to new public methods for clarity

Add missing documentation for browser extension integration and WebSocket protocol

The README mentions browser extensions are required for web browsing statistics, and the code has Core/Librarys/Browser/WebSocketEvent.cs and favicon downloading logic, but there's no technical documentation explaining the WebSocket protocol between browser extensions and Tai, expected message formats, or how to debug extension communication. This blocks extension developers from contributing.

  • [ ] Create docs/BROWSER_EXTENSION_PROTOCOL.md documenting WebSocket message formats and event flow
  • [ ] Document the Site.cs model structure and what fields extensions must provide
  • [ ] Explain favicon caching strategy in FaviconDownloader.cs and when/how it's triggered
  • [ ] Document BrowserObserverEventHandler.cs event types and when they're fired
  • [ ] Add troubleshooting section for common WebSocket connection issues
  • [ ] Include example extension payload JSON in the documentation

🌿Good first issues

  • Add automated unit tests for Core/Librarys/RegexHelper.cs—filter/categorization logic currently has no test coverage; write test cases for common regex patterns used in app/URL filtering to prevent regressions
  • Implement proper logging rotation in Core/Librarys/Logger.cs—currently appears to be unbounded growth; add configurable file size limits and archive old logs to improve long-term stability on low-storage systems
  • Document the WebSocket protocol contract between browser extension and Core/Librarys/Browser/WebSocketEvent.cs—create a .md file in docs/ specifying the JSON message format, required fields, and error handling expectations to unblock third-party extension developers

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 566062d — Update README.md (noberumotto)
  • 499c72e — 别名最大长度上限调整为15;允许清空别名 (nacatcode)
  • f090e50 — 增加浏览器插件功能说明和链接 (nacatcode)
  • c939c5a — 增加别名设置功能 (nacatcode)
  • c0f2bda — fix:#299 (nacatcode)
  • 5d7964a — Update README.md (noberumotto)
  • de527e5 — 数据库实体模型bool类型创建 (noberumotto)
  • a841d1a — 添加删除分类确认弹窗 (noberumotto)
  • cd81aa8 — 修复添加分类匹配目录一些问题 (noberumotto)
  • 14550b4 — 添加根据运行目录自动分类功能 (noberumotto)

🔒Security observations

  • High · Potential SQL Injection via SQLiteBuilder — Core/Librarys/SQLite/SQLiteBuilder.cs. The SQLiteBuilder class is used for database operations. Without seeing the actual implementation, common SQL injection vulnerabilities can occur when user input is directly concatenated into SQL queries. The presence of dynamic query building in SQLite contexts poses significant risk. Fix: Ensure all SQL queries use parameterized queries/prepared statements. Avoid string concatenation for building SQL queries. Validate and sanitize all user inputs before database operations.
  • High · Potential XSS via Web Server Component — Core/Servicers/Instances/WebServer.cs, Core/Librarys/Browser/WebSocketEvent.cs. The WebServer and WebSocketEvent components handle web-based communication. Browser extension communication and web page data could be vulnerable to XSS if not properly sanitized. The presence of WebPageInfo and Site models suggests dynamic content handling. Fix: Implement strict output encoding for all web-based communications. Use Content Security Policy (CSP) headers. Sanitize all user-provided data before rendering in web contexts.
  • High · Registry Operations Without Validation — Core/Librarys/Win32API.cs. The Win32API module likely contains registry operations for accessing system information. Improper handling of registry data could lead to injection attacks or unauthorized system modification. Fix: Validate all registry keys and values before use. Implement strict access controls for registry operations. Use only necessary registry access permissions.
  • Medium · Favicon Download Without Security Validation — Core/Librarys/Browser/Favicon/FaviconDownloader.cs. FaviconDownloader downloads and caches favicons from arbitrary URLs. This could be exploited for SSRF (Server-Side Request Forgery), malicious file execution, or denial of service attacks. Fix: Implement URL validation and whitelist. Restrict file sizes for downloads. Validate file types and contents. Implement timeout mechanisms. Use sandboxing for favicon processing.
  • Medium · Process Monitoring Without Privilege Escalation Control — Core/Librarys/ProcessHelper.cs, Core/Servicers/Instances/AppObserver.cs. ProcessHelper monitors running processes and application window information. The requirement to run as administrator combined with process hooking could be exploited. No visible privilege validation or control mechanisms. Fix: Implement privilege validation. Use principle of least privilege. Document why admin access is required. Implement privilege escalation detection. Use secure APIs for process monitoring.
  • Medium · File Operations Without Path Traversal Validation — Core/Librarys/FileHelper.cs. FileHelper class handles file operations. Without visible path validation, attackers could potentially exploit path traversal vulnerabilities to access unauthorized files on the system. Fix: Implement strict path validation. Use Path.GetFullPath() and verify canonical paths. Maintain a whitelist of allowed directories. Reject paths containing '..', symlinks, and junction points.
  • Medium · Configuration Exposure Risk — Core/App.config, Core/Models/Config/ConfigModel.cs. Configuration data stored in App.config and various Config models may contain sensitive information. No visible encryption for sensitive config values. Fix: Encrypt sensitive configuration values. Store sensitive data in secure configuration stores (Windows Credential Manager, Azure Key Vault). Never hardcode credentials or API keys in config files.
  • Medium · Insufficient Logging and Monitoring — Core/Librarys/Logger.cs. While Logger.cs exists, there's no visibility into what security events are logged. Sensitive operations like privilege usage, file access, and network operations may not be properly audited. Fix: Implement comprehensive security logging. Log all privileged operations, file access attempts, network communications, and authentication events. Protect logs from tampering.
  • Low · Base64 Encoded Contact Information in README — README.md. The README contains base64 encoded contact information. While low severity, this indicates possible obfuscation practices that could mask other sensitive data in the codebase. Fix: Use standard contact formats without encoding. If obfuscation is needed, document the reason.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · Planshit/Tai — RepoPilot