@hirra/vibemeter 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +12 -0
- package/.next/build/chunks/[root-of-the-server]__0d-m0h0._.js +206 -0
- package/.next/build/chunks/[root-of-the-server]__0d-m0h0._.js.map +8 -0
- package/.next/build/chunks/[root-of-the-server]__0ubbtyl._.js +500 -0
- package/.next/build/chunks/[root-of-the-server]__0ubbtyl._.js.map +11 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_06e.r3r._.js +13 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_06e.r3r._.js.map +5 -0
- package/.next/build/chunks/[turbopack]_runtime.js +890 -0
- package/.next/build/chunks/[turbopack]_runtime.js.map +11 -0
- package/.next/build/chunks/node_modules_13sb.px._.js +6815 -0
- package/.next/build/chunks/node_modules_13sb.px._.js.map +47 -0
- package/.next/build/package.json +1 -0
- package/.next/build/postcss.js +6 -0
- package/.next/build/postcss.js.map +5 -0
- package/.next/build-manifest.json +21 -0
- package/.next/export-marker.json +6 -0
- package/.next/fallback-build-manifest.json +13 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +90 -0
- package/.next/required-server-files.js +335 -0
- package/.next/required-server-files.json +335 -0
- package/.next/routes-manifest.json +108 -0
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +17 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +10 -0
- package/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +15 -0
- package/.next/server/app/_global-error.rsc +15 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +17 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_not-found/page.js +13 -0
- package/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +16 -0
- package/.next/server/app/_not-found.rsc +16 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +16 -0
- package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_index.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/admin/page/app-paths-manifest.json +3 -0
- package/.next/server/app/admin/page/build-manifest.json +17 -0
- package/.next/server/app/admin/page/next-font-manifest.json +11 -0
- package/.next/server/app/admin/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/admin/page/server-reference-manifest.json +4 -0
- package/.next/server/app/admin/page.js +14 -0
- package/.next/server/app/admin/page.js.map +5 -0
- package/.next/server/app/admin/page.js.nft.json +1 -0
- package/.next/server/app/admin/page_client-reference-manifest.js +3 -0
- package/.next/server/app/api/codex-accounts/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/codex-accounts/route/build-manifest.json +9 -0
- package/.next/server/app/api/codex-accounts/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/codex-accounts/route.js +6 -0
- package/.next/server/app/api/codex-accounts/route.js.map +5 -0
- package/.next/server/app/api/codex-accounts/route.js.nft.json +1 -0
- package/.next/server/app/api/codex-accounts/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/import-sessions/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/import-sessions/route/build-manifest.json +9 -0
- package/.next/server/app/api/import-sessions/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/import-sessions/route.js +6 -0
- package/.next/server/app/api/import-sessions/route.js.map +5 -0
- package/.next/server/app/api/import-sessions/route.js.nft.json +1 -0
- package/.next/server/app/api/import-sessions/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/sessions/[id]/tags/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/sessions/[id]/tags/route/build-manifest.json +9 -0
- package/.next/server/app/api/sessions/[id]/tags/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/sessions/[id]/tags/route.js +7 -0
- package/.next/server/app/api/sessions/[id]/tags/route.js.map +5 -0
- package/.next/server/app/api/sessions/[id]/tags/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/[id]/tags/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/sessions/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/sessions/route/build-manifest.json +9 -0
- package/.next/server/app/api/sessions/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/sessions/route.js +6 -0
- package/.next/server/app/api/sessions/route.js.map +5 -0
- package/.next/server/app/api/sessions/route.js.nft.json +1 -0
- package/.next/server/app/api/sessions/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/usage/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/usage/route/build-manifest.json +9 -0
- package/.next/server/app/api/usage/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/usage/route.js +6 -0
- package/.next/server/app/api/usage/route.js.map +5 -0
- package/.next/server/app/api/usage/route.js.nft.json +1 -0
- package/.next/server/app/api/usage/route_client-reference-manifest.js +3 -0
- package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/server/app/favicon.ico/route/build-manifest.json +9 -0
- package/.next/server/app/favicon.ico/route.js +7 -0
- package/.next/server/app/favicon.ico/route.js.map +5 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +17 -0
- package/.next/server/app/page/next-font-manifest.json +11 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +4 -0
- package/.next/server/app/page.js +14 -0
- package/.next/server/app/page.js.map +5 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +3 -0
- package/.next/server/app-paths-manifest.json +12 -0
- package/.next/server/chunks/[externals]_next_dist_0arv.vj._.js +3 -0
- package/.next/server/chunks/[externals]_next_dist_0arv.vj._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0-74syk._.js +4 -0
- package/.next/server/chunks/[root-of-the-server]__0-74syk._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__00q0o~z._.js +41 -0
- package/.next/server/chunks/[root-of-the-server]__00q0o~z._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0866q87._.js +44 -0
- package/.next/server/chunks/[root-of-the-server]__0866q87._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0ade2u0._.js +96 -0
- package/.next/server/chunks/[root-of-the-server]__0ade2u0._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0chedn~._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0chedn~._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0j8-xkl._.js +13 -0
- package/.next/server/chunks/[root-of-the-server]__0j8-xkl._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0ub_1u.._.js +63 -0
- package/.next/server/chunks/[root-of-the-server]__0ub_1u.._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +903 -0
- package/.next/server/chunks/[turbopack]_runtime.js.map +11 -0
- package/.next/server/chunks/_next-internal_server_app_api_codex-accounts_route_actions_0mvn0sb.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_codex-accounts_route_actions_0mvn0sb.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_import-sessions_route_actions_0gcv3u8.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_import-sessions_route_actions_0gcv3u8.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_tags_route_actions_0qemhrr.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_sessions_[id]_tags_route_actions_0qemhrr.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_sessions_route_actions_0y1t9w0.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_sessions_route_actions_0y1t9w0.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_usage_route_actions_0rd63ni.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_usage_route_actions_0rd63ni.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_095lj93.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_095lj93.js.map +1 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0m.429v.js +3 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0m.429v.js.map +1 -0
- package/.next/server/chunks/node_modules_zod_v4_classic_external_131y~ke.js +64 -0
- package/.next/server/chunks/node_modules_zod_v4_classic_external_131y~ke.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__02g_-ps._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__02g_-ps._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__054lv8d._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__054lv8d._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__08qr2ji._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__08qr2ji._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__098zro9._.js +19 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__098zro9._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__09hgk-7._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__09hgk-7._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0cqes87._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0cqes87._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0l.drdn._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0l.drdn._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0v1zqf~._.js +120 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0v1zqf~._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0v73tbn._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0v73tbn._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +903 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +11 -0
- package/.next/server/chunks/ssr/_0ye~8el._.js +7 -0
- package/.next/server/chunks/ssr/_0ye~8el._.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0eq97pa.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_admin_page_actions_0ycnu8f.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_admin_page_actions_0ycnu8f.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_09w7yel._.js +33 -0
- package/.next/server/chunks/ssr/node_modules_09w7yel._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_0ck2~9g._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_0ck2~9g._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_0i2xw~e._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_0i2xw~e._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js +6 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0gsjr7_._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0gsjr7_._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0inhx6q._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0inhx6q._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03-z2qq.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03-z2qq.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_07vh7rm.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_07vh7rm.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0l5h-6w.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0l5h-6w.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0qp4u6g.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0qp4u6g.js.map +1 -0
- package/.next/server/chunks/ssr/src_components_CodexAccountsPanel_tsx_0n9xjzi._.js +3 -0
- package/.next/server/chunks/ssr/src_components_CodexAccountsPanel_tsx_0n9xjzi._.js.map +1 -0
- package/.next/server/functions-config-manifest.json +7 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +21 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +19 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +5 -0
- package/.next/static/chunks/002~6040mndie.css +3 -0
- package/.next/static/chunks/00gq-v0e07i1q.js +31 -0
- package/.next/static/chunks/01xlw8hd842-c.js +1 -0
- package/.next/static/chunks/02g3221oh~3le.js +2 -0
- package/.next/static/chunks/03~yq9q893hmn.js +1 -0
- package/.next/static/chunks/05t54y~yfn5og.js +2 -0
- package/.next/static/chunks/07lhk_q6pmm3r.js +1 -0
- package/.next/static/chunks/0d3shmwh5_nmn.js +1 -0
- package/.next/static/chunks/0ljfidstam_7k.js +1 -0
- package/.next/static/chunks/0pqt~8bl3ukh4.js +4 -0
- package/.next/static/chunks/turbopack-14vio.b1b9i4l.js +1 -0
- package/.next/static/fZRw0LZi2i6aUKKet_Evv/_buildManifest.js +11 -0
- package/.next/static/fZRw0LZi2i6aUKKet_Evv/_clientMiddlewareManifest.js +1 -0
- package/.next/static/fZRw0LZi2i6aUKKet_Evv/_ssgManifest.js +1 -0
- package/.next/static/media/4fa387ec64143e14-s.0.qu-9752pffj.woff2 +0 -0
- package/.next/static/media/53b9e256198e5412-s.0-wfv7uh4i7h9.woff2 +0 -0
- package/.next/static/media/5ce348bf30bf5439-s.0ee55_hj9qcer.woff2 +0 -0
- package/.next/static/media/6306c77e7c8268e4-s.0mao5jbfbduzp.woff2 +0 -0
- package/.next/static/media/7178b3e590c64307-s.0nx0ww8fni_q3.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2 +0 -0
- package/.next/static/media/7d817b4c03b0c5f1-s.0uzt.a6d44yda.woff2 +0 -0
- package/.next/static/media/8a480f0b521d4e75-s.0jzbimsg8vl84.woff2 +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.0mvwgmnhv29no.woff2 +0 -0
- package/.next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2 +0 -0
- package/.next/static/media/favicon.0x3dzn~oxb6tn.ico +0 -0
- package/.next/static/media/fef07dbb0973bf53-s.12tyk43_3sh9u.woff2 +0 -0
- package/.next/types/cache-life.d.ts +145 -0
- package/.next/types/routes.d.ts +78 -0
- package/.next/types/validator.ts +124 -0
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/bin/vibemeter.mjs +221 -0
- package/docs/demo1.png +0 -0
- package/next.config.mjs +8 -0
- package/package.json +51 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// This file is generated automatically by Next.js
|
|
2
|
+
// Do not edit this file manually
|
|
3
|
+
// This file validates that all pages and layouts export the correct types
|
|
4
|
+
|
|
5
|
+
import type { AppRoutes, LayoutRoutes, ParamMap, AppRouteHandlerRoutes } from "./routes.js"
|
|
6
|
+
import type { ResolvingMetadata, ResolvingViewport } from "next/types.js"
|
|
7
|
+
import type { NextRequest } from 'next/server.js'
|
|
8
|
+
|
|
9
|
+
type AppPageConfig<Route extends AppRoutes = AppRoutes> = {
|
|
10
|
+
default: React.ComponentType<{ params: Promise<ParamMap[Route]> } & any> | ((props: { params: Promise<ParamMap[Route]> } & any) => React.ReactNode | Promise<React.ReactNode> | never | void | Promise<void>)
|
|
11
|
+
generateStaticParams?: (props: { params: ParamMap[Route] }) => Promise<any[]> | any[]
|
|
12
|
+
generateMetadata?: (
|
|
13
|
+
props: { params: Promise<ParamMap[Route]> } & any,
|
|
14
|
+
parent: ResolvingMetadata
|
|
15
|
+
) => Promise<any> | any
|
|
16
|
+
generateViewport?: (
|
|
17
|
+
props: { params: Promise<ParamMap[Route]> } & any,
|
|
18
|
+
parent: ResolvingViewport
|
|
19
|
+
) => Promise<any> | any
|
|
20
|
+
metadata?: any
|
|
21
|
+
viewport?: any
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type LayoutConfig<Route extends LayoutRoutes = LayoutRoutes> = {
|
|
25
|
+
default: React.ComponentType<LayoutProps<Route>> | ((props: LayoutProps<Route>) => React.ReactNode | Promise<React.ReactNode> | never | void | Promise<void>)
|
|
26
|
+
generateStaticParams?: (props: { params: ParamMap[Route] }) => Promise<any[]> | any[]
|
|
27
|
+
generateMetadata?: (
|
|
28
|
+
props: { params: Promise<ParamMap[Route]> } & any,
|
|
29
|
+
parent: ResolvingMetadata
|
|
30
|
+
) => Promise<any> | any
|
|
31
|
+
generateViewport?: (
|
|
32
|
+
props: { params: Promise<ParamMap[Route]> } & any,
|
|
33
|
+
parent: ResolvingViewport
|
|
34
|
+
) => Promise<any> | any
|
|
35
|
+
metadata?: any
|
|
36
|
+
viewport?: any
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRoutes> = {
|
|
40
|
+
GET?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
41
|
+
POST?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
42
|
+
PUT?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
43
|
+
PATCH?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
44
|
+
DELETE?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
45
|
+
HEAD?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
46
|
+
OPTIONS?: (request: NextRequest, context: { params: Promise<ParamMap[Route]> }) => Promise<Response | void> | Response | void
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
// Validate ../../src/app/admin/page.tsx
|
|
51
|
+
{
|
|
52
|
+
type __IsExpected<Specific extends AppPageConfig<"/admin">> = Specific
|
|
53
|
+
const handler = {} as typeof import("../../src/app/admin/page.js")
|
|
54
|
+
type __Check = __IsExpected<typeof handler>
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
type __Unused = __Check
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Validate ../../src/app/page.tsx
|
|
60
|
+
{
|
|
61
|
+
type __IsExpected<Specific extends AppPageConfig<"/">> = Specific
|
|
62
|
+
const handler = {} as typeof import("../../src/app/page.js")
|
|
63
|
+
type __Check = __IsExpected<typeof handler>
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
type __Unused = __Check
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Validate ../../src/app/api/codex-accounts/route.ts
|
|
69
|
+
{
|
|
70
|
+
type __IsExpected<Specific extends RouteHandlerConfig<"/api/codex-accounts">> = Specific
|
|
71
|
+
const handler = {} as typeof import("../../src/app/api/codex-accounts/route.js")
|
|
72
|
+
type __Check = __IsExpected<typeof handler>
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
type __Unused = __Check
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Validate ../../src/app/api/import-sessions/route.ts
|
|
78
|
+
{
|
|
79
|
+
type __IsExpected<Specific extends RouteHandlerConfig<"/api/import-sessions">> = Specific
|
|
80
|
+
const handler = {} as typeof import("../../src/app/api/import-sessions/route.js")
|
|
81
|
+
type __Check = __IsExpected<typeof handler>
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
type __Unused = __Check
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Validate ../../src/app/api/sessions/[id]/tags/route.ts
|
|
87
|
+
{
|
|
88
|
+
type __IsExpected<Specific extends RouteHandlerConfig<"/api/sessions/[id]/tags">> = Specific
|
|
89
|
+
const handler = {} as typeof import("../../src/app/api/sessions/[id]/tags/route.js")
|
|
90
|
+
type __Check = __IsExpected<typeof handler>
|
|
91
|
+
// @ts-ignore
|
|
92
|
+
type __Unused = __Check
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Validate ../../src/app/api/sessions/route.ts
|
|
96
|
+
{
|
|
97
|
+
type __IsExpected<Specific extends RouteHandlerConfig<"/api/sessions">> = Specific
|
|
98
|
+
const handler = {} as typeof import("../../src/app/api/sessions/route.js")
|
|
99
|
+
type __Check = __IsExpected<typeof handler>
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
type __Unused = __Check
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Validate ../../src/app/api/usage/route.ts
|
|
105
|
+
{
|
|
106
|
+
type __IsExpected<Specific extends RouteHandlerConfig<"/api/usage">> = Specific
|
|
107
|
+
const handler = {} as typeof import("../../src/app/api/usage/route.js")
|
|
108
|
+
type __Check = __IsExpected<typeof handler>
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
type __Unused = __Check
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
// Validate ../../src/app/layout.tsx
|
|
118
|
+
{
|
|
119
|
+
type __IsExpected<Specific extends LayoutConfig<"/">> = Specific
|
|
120
|
+
const handler = {} as typeof import("../../src/app/layout.js")
|
|
121
|
+
type __Check = __IsExpected<typeof handler>
|
|
122
|
+
// @ts-ignore
|
|
123
|
+
type __Unused = __Check
|
|
124
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hirra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Vibemeter
|
|
2
|
+
|
|
3
|
+
> Measure your AI coding vibe. A local-first dashboard for Claude Code, Codex, and Cursor.
|
|
4
|
+
|
|
5
|
+
> 🔒 **Everything runs locally. No data ever leaves your machine.** No telemetry, no tracking, no cloud, no API calls out. Vibemeter reads files already on your disk and renders a dashboard from them. That's it.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## What you get
|
|
10
|
+
|
|
11
|
+
- **5h / 7-day rate-limit windows** for both Claude Code (statusline) and Codex (rollout files)
|
|
12
|
+
- **Spending & consumption** — Claude Code USD + Codex tokens, with a 14-day trend chart
|
|
13
|
+
- **Activity** — hour-of-week heatmap with peak-slot detection + today's timeline ribbon
|
|
14
|
+
- **Project leaderboard** — top projects by hours / sessions / tools used
|
|
15
|
+
- **Achievements** — 16 unlockable milestones
|
|
16
|
+
- **Burndown chart** — 7-day usage history with hover tooltip
|
|
17
|
+
- **Sessions table** — searchable, tag-able, filterable by tool and date range
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @hirra/vibemeter
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Open <http://localhost:9527>. Data lives in `~/.vibemeter/`.
|
|
26
|
+
|
|
27
|
+
That's the whole install. Hit Ctrl-C to stop.
|
|
28
|
+
|
|
29
|
+
## Run as a background service (macOS)
|
|
30
|
+
|
|
31
|
+
Want it always running on login? One command:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx @hirra/vibemeter install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This registers a LaunchAgent at `~/Library/LaunchAgents/com.hirra.vibemeter.plist`. It boots on login, restarts if it crashes, and writes logs to `~/.vibemeter/vibemeter.log`.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx @hirra/vibemeter status # see if it's loaded + tail the log
|
|
41
|
+
npx @hirra/vibemeter uninstall # remove the LaunchAgent
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
On Linux, run `vibemeter install` and it'll print a systemd-user unit you can drop in `~/.config/systemd/user/vibemeter.service`.
|
|
45
|
+
|
|
46
|
+
## CLI reference
|
|
47
|
+
|
|
48
|
+
| Command | What it does |
|
|
49
|
+
| ---------------------- | ---------------------------------------------------- |
|
|
50
|
+
| `vibemeter` | start the server in the foreground (Ctrl-C to stop) |
|
|
51
|
+
| `vibemeter install` | register a LaunchAgent so it runs on login (macOS) |
|
|
52
|
+
| `vibemeter uninstall` | remove the auto-start config |
|
|
53
|
+
| `vibemeter status` | show whether the daemon is loaded + tail log |
|
|
54
|
+
| `vibemeter help` | print usage |
|
|
55
|
+
|
|
56
|
+
| Env var | Default |
|
|
57
|
+
| --------------------- | ---------------- |
|
|
58
|
+
| `PORT` | `9527` |
|
|
59
|
+
| `VIBEMETER_DATA_DIR` | `~/.vibemeter` |
|
|
60
|
+
|
|
61
|
+
## Where the data comes from
|
|
62
|
+
|
|
63
|
+
Vibemeter reads these files directly. Nothing is sent anywhere.
|
|
64
|
+
|
|
65
|
+
| Tool | Source |
|
|
66
|
+
| ----------- | ---------------------------------------------------------------------------- |
|
|
67
|
+
| Claude Code | `~/.claude/projects/**/*.jsonl` |
|
|
68
|
+
| Claude Code | `~/.claude/sessions/*.json` (active-session flag) |
|
|
69
|
+
| Codex | `~/.codex/state_5.sqlite` (thread metadata) |
|
|
70
|
+
| Codex | `~/.codex/sessions/**/rollout-*.jsonl` (rate-limit windows) |
|
|
71
|
+
| Cursor | `~/Library/Application Support/Cursor/User/workspaceStorage/**/state.vscdb` |
|
|
72
|
+
|
|
73
|
+
If a tool's files don't exist, its cards just show "no data yet". Everything else still works.
|
|
74
|
+
|
|
75
|
+
## Claude Code 5h / 7-day cards (optional setup)
|
|
76
|
+
|
|
77
|
+
These cards need a statusline hook. Add this to `~/.claude/settings.json`:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"statusLine": {
|
|
82
|
+
"type": "command",
|
|
83
|
+
"command": "node -e \"const fs=require('fs'),os=require('os'),p=require('path');const d=p.join(os.homedir(),'.vibemeter');fs.mkdirSync(d,{recursive:true});fs.writeFileSync(p.join(d,'statusline-latest.json'),fs.readFileSync(0));\""
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Claude Code starts writing `~/.vibemeter/statusline-latest.json` on every status-line render. Vibemeter picks it up automatically.
|
|
89
|
+
|
|
90
|
+
Codex needs **no setup** — its 5h/7d data lives in `~/.codex/sessions/**/rollout-*.jsonl` already.
|
|
91
|
+
|
|
92
|
+
## Demo mode
|
|
93
|
+
|
|
94
|
+
Append `?demo=1` to the URL — anonymizes project names and injects mock sessions. Useful for screenshots and screen-sharing.
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
http://localhost:9527/?demo=1
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Run from source
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git clone https://github.com/myhirra/Vibemeter.git
|
|
104
|
+
cd Vibemeter
|
|
105
|
+
npm install
|
|
106
|
+
npm run dev
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Source mode uses `./.data/` instead of `~/.vibemeter/`. Override with `VIBEMETER_DATA_DIR=...`.
|
|
110
|
+
|
|
111
|
+
## Tech stack
|
|
112
|
+
|
|
113
|
+
- Next.js 16 (App Router, Turbopack), React 19, Tailwind v4
|
|
114
|
+
- better-sqlite3 for local storage
|
|
115
|
+
- Zero external services. Zero telemetry. Zero tracking.
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Vibemeter CLI — `npx @hirra/vibemeter`
|
|
4
|
+
*
|
|
5
|
+
* vibemeter start the server in the foreground
|
|
6
|
+
* vibemeter install register as a LaunchAgent so it boots on login (macOS)
|
|
7
|
+
* vibemeter uninstall remove the LaunchAgent
|
|
8
|
+
* vibemeter status show whether the daemon is loaded / running
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { dirname, join, resolve as resolvePath } from 'node:path';
|
|
15
|
+
import { homedir, platform } from 'node:os';
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const ROOT = join(__dirname, '..');
|
|
20
|
+
const DEFAULT_PORT = 9527;
|
|
21
|
+
const PORT = process.env.PORT ?? String(DEFAULT_PORT);
|
|
22
|
+
const DATA_DIR = process.env.VIBEMETER_DATA_DIR ?? join(homedir(), '.vibemeter');
|
|
23
|
+
const LABEL = 'com.hirra.vibemeter';
|
|
24
|
+
const PLIST_PATH = join(homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`);
|
|
25
|
+
|
|
26
|
+
process.env.VIBEMETER_DATA_DIR = DATA_DIR;
|
|
27
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
28
|
+
|
|
29
|
+
const require = createRequire(import.meta.url);
|
|
30
|
+
function resolveNextBin() {
|
|
31
|
+
try {
|
|
32
|
+
return require.resolve('next/dist/bin/next', { paths: [ROOT] });
|
|
33
|
+
} catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function runNext(args) {
|
|
39
|
+
const nextBin = resolveNextBin();
|
|
40
|
+
if (!nextBin) {
|
|
41
|
+
console.error('Vibemeter: could not locate the `next` package. Try reinstalling.');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
return new Promise((resolveP, reject) => {
|
|
45
|
+
const p = spawn(process.execPath, [nextBin, ...args], { cwd: ROOT, stdio: 'inherit' });
|
|
46
|
+
p.on('exit', (code) => code === 0 ? resolveP() : reject(new Error(`next ${args[0]} exit ${code}`)));
|
|
47
|
+
for (const sig of ['SIGINT', 'SIGTERM']) process.on(sig, () => p.kill(sig));
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function start() {
|
|
52
|
+
if (!existsSync(join(ROOT, '.next', 'BUILD_ID'))) {
|
|
53
|
+
console.error('First run — building Vibemeter (one-time, ~30s)…');
|
|
54
|
+
await runNext(['build']).catch((e) => { console.error(e.message); process.exit(1); });
|
|
55
|
+
}
|
|
56
|
+
console.error('');
|
|
57
|
+
console.error(' Vibemeter');
|
|
58
|
+
console.error(` → http://localhost:${PORT}`);
|
|
59
|
+
console.error(` data: ${DATA_DIR}`);
|
|
60
|
+
console.error(' (Ctrl-C to stop)');
|
|
61
|
+
console.error('');
|
|
62
|
+
await runNext(['start', '-p', String(PORT)]).catch((e) => { console.error(e.message); process.exit(1); });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function plistXml({ nodeBin, scriptPath, logPath, port, dataDir }) {
|
|
66
|
+
const esc = (s) => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
67
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
68
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
69
|
+
<plist version="1.0">
|
|
70
|
+
<dict>
|
|
71
|
+
<key>Label</key>
|
|
72
|
+
<string>${LABEL}</string>
|
|
73
|
+
<key>ProgramArguments</key>
|
|
74
|
+
<array>
|
|
75
|
+
<string>${esc(nodeBin)}</string>
|
|
76
|
+
<string>${esc(scriptPath)}</string>
|
|
77
|
+
</array>
|
|
78
|
+
<key>RunAtLoad</key><true/>
|
|
79
|
+
<key>KeepAlive</key><true/>
|
|
80
|
+
<key>StandardOutPath</key><string>${esc(logPath)}</string>
|
|
81
|
+
<key>StandardErrorPath</key><string>${esc(logPath)}</string>
|
|
82
|
+
<key>EnvironmentVariables</key>
|
|
83
|
+
<dict>
|
|
84
|
+
<key>PATH</key><string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
85
|
+
<key>PORT</key><string>${esc(port)}</string>
|
|
86
|
+
<key>VIBEMETER_DATA_DIR</key><string>${esc(dataDir)}</string>
|
|
87
|
+
<key>NODE_ENV</key><string>production</string>
|
|
88
|
+
</dict>
|
|
89
|
+
</dict>
|
|
90
|
+
</plist>
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function systemdUnit({ nodeBin, scriptPath, port, dataDir }) {
|
|
95
|
+
return `[Unit]
|
|
96
|
+
Description=Vibemeter — local AI coding dashboard
|
|
97
|
+
After=network.target
|
|
98
|
+
|
|
99
|
+
[Service]
|
|
100
|
+
ExecStart=${nodeBin} ${scriptPath}
|
|
101
|
+
Restart=on-failure
|
|
102
|
+
RestartSec=5
|
|
103
|
+
Environment=PORT=${port}
|
|
104
|
+
Environment=VIBEMETER_DATA_DIR=${dataDir}
|
|
105
|
+
Environment=NODE_ENV=production
|
|
106
|
+
|
|
107
|
+
[Install]
|
|
108
|
+
WantedBy=default.target
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function macInstall() {
|
|
113
|
+
const scriptPath = resolvePath(fileURLToPath(import.meta.url));
|
|
114
|
+
const logPath = join(DATA_DIR, 'vibemeter.log');
|
|
115
|
+
mkdirSync(dirname(PLIST_PATH), { recursive: true });
|
|
116
|
+
writeFileSync(PLIST_PATH, plistXml({
|
|
117
|
+
nodeBin: process.execPath, scriptPath, logPath, port: PORT, dataDir: DATA_DIR,
|
|
118
|
+
}));
|
|
119
|
+
// Reload: unload first (ignore errors), then load
|
|
120
|
+
spawnSync('launchctl', ['unload', PLIST_PATH], { stdio: 'ignore' });
|
|
121
|
+
const r = spawnSync('launchctl', ['load', PLIST_PATH], { stdio: 'inherit' });
|
|
122
|
+
if (r.status !== 0) {
|
|
123
|
+
console.error('launchctl load failed.');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
console.log('');
|
|
127
|
+
console.log(' ✓ Vibemeter installed as LaunchAgent');
|
|
128
|
+
console.log(` plist: ${PLIST_PATH}`);
|
|
129
|
+
console.log(` log: ${logPath}`);
|
|
130
|
+
console.log(` URL: http://localhost:${PORT}`);
|
|
131
|
+
console.log('');
|
|
132
|
+
console.log(' It will start automatically on login and restart if it crashes.');
|
|
133
|
+
console.log(' Use `vibemeter uninstall` to remove.');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function macUninstall() {
|
|
137
|
+
if (!existsSync(PLIST_PATH)) {
|
|
138
|
+
console.log('Vibemeter LaunchAgent is not installed.');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
spawnSync('launchctl', ['unload', PLIST_PATH], { stdio: 'ignore' });
|
|
142
|
+
rmSync(PLIST_PATH);
|
|
143
|
+
console.log(`✓ Removed ${PLIST_PATH}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function macStatus() {
|
|
147
|
+
const list = spawnSync('launchctl', ['list', LABEL], { encoding: 'utf8' });
|
|
148
|
+
if (list.status !== 0) {
|
|
149
|
+
console.log(`Not loaded. (Run \`vibemeter install\` to register.)`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log(list.stdout.trim());
|
|
153
|
+
console.log('');
|
|
154
|
+
const log = join(DATA_DIR, 'vibemeter.log');
|
|
155
|
+
if (existsSync(log)) {
|
|
156
|
+
console.log(`Recent log (tail of ${log}):`);
|
|
157
|
+
try {
|
|
158
|
+
const body = readFileSync(log, 'utf8').trim().split('\n').slice(-15).join('\n');
|
|
159
|
+
console.log(body || '(empty)');
|
|
160
|
+
} catch { /* ignore */ }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function linuxInstallHint() {
|
|
165
|
+
const scriptPath = resolvePath(fileURLToPath(import.meta.url));
|
|
166
|
+
const unitPath = join(homedir(), '.config', 'systemd', 'user', 'vibemeter.service');
|
|
167
|
+
console.log('On Linux, write the following to ~/.config/systemd/user/vibemeter.service:\n');
|
|
168
|
+
console.log(systemdUnit({ nodeBin: process.execPath, scriptPath, port: PORT, dataDir: DATA_DIR }));
|
|
169
|
+
console.log('Then run:');
|
|
170
|
+
console.log(` systemctl --user daemon-reload`);
|
|
171
|
+
console.log(` systemctl --user enable --now vibemeter`);
|
|
172
|
+
console.log(` loginctl enable-linger ${process.env.USER ?? ''} # so it keeps running when logged out`);
|
|
173
|
+
console.log(`\n(target file: ${unitPath})`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function help() {
|
|
177
|
+
console.log(`
|
|
178
|
+
Vibemeter — local AI coding dashboard
|
|
179
|
+
|
|
180
|
+
Usage:
|
|
181
|
+
vibemeter start the server in the foreground (Ctrl-C to stop)
|
|
182
|
+
vibemeter install run on login + keep alive (macOS LaunchAgent)
|
|
183
|
+
vibemeter uninstall remove the auto-start config
|
|
184
|
+
vibemeter status show whether the daemon is loaded + tail logs
|
|
185
|
+
vibemeter help this message
|
|
186
|
+
|
|
187
|
+
Environment:
|
|
188
|
+
PORT default ${DEFAULT_PORT}
|
|
189
|
+
VIBEMETER_DATA_DIR default ~/.vibemeter
|
|
190
|
+
`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const cmd = process.argv[2];
|
|
194
|
+
switch (cmd) {
|
|
195
|
+
case undefined:
|
|
196
|
+
case 'start':
|
|
197
|
+
await start();
|
|
198
|
+
break;
|
|
199
|
+
case 'install':
|
|
200
|
+
if (platform() === 'darwin') macInstall();
|
|
201
|
+
else if (platform() === 'linux') linuxInstallHint();
|
|
202
|
+
else { console.error('Auto-start install not implemented for this platform yet.'); process.exit(1); }
|
|
203
|
+
break;
|
|
204
|
+
case 'uninstall':
|
|
205
|
+
if (platform() === 'darwin') macUninstall();
|
|
206
|
+
else { console.error('Auto-start uninstall not implemented for this platform yet.'); process.exit(1); }
|
|
207
|
+
break;
|
|
208
|
+
case 'status':
|
|
209
|
+
if (platform() === 'darwin') macStatus();
|
|
210
|
+
else { console.error('Status not implemented for this platform yet.'); process.exit(1); }
|
|
211
|
+
break;
|
|
212
|
+
case '-h':
|
|
213
|
+
case '--help':
|
|
214
|
+
case 'help':
|
|
215
|
+
help();
|
|
216
|
+
break;
|
|
217
|
+
default:
|
|
218
|
+
console.error(`Unknown command: ${cmd}\n`);
|
|
219
|
+
help();
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
package/docs/demo1.png
ADDED
|
Binary file
|
package/next.config.mjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @type {import('next').NextConfig} */
|
|
2
|
+
const nextConfig = {
|
|
3
|
+
// Keep native modules out of the bundle — they're resolved from node_modules at runtime,
|
|
4
|
+
// which lets npm install the correct binary on the user's platform.
|
|
5
|
+
serverExternalPackages: ['better-sqlite3'],
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default nextConfig;
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hirra/vibemeter",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local-first dashboard for your AI coding life — Claude Code, Codex, Cursor session tracking with usage windows, spending, heatmaps, and achievements.",
|
|
5
|
+
"keywords": ["claude-code", "codex", "cursor", "dashboard", "ai-coding", "session-tracking", "local-first"],
|
|
6
|
+
"homepage": "https://github.com/myhirra/Vibemeter",
|
|
7
|
+
"repository": { "type": "git", "url": "git+https://github.com/myhirra/Vibemeter.git" },
|
|
8
|
+
"publishConfig": { "access": "public" },
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "hirra <myhirra@126.com>",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"vibemeter": "bin/vibemeter.mjs"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
".next",
|
|
17
|
+
"public",
|
|
18
|
+
"bin",
|
|
19
|
+
"docs",
|
|
20
|
+
"next.config.mjs"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"dev": "next dev",
|
|
24
|
+
"build": "next build",
|
|
25
|
+
"start": "next start",
|
|
26
|
+
"lint": "eslint",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"prepack": "rm -rf .next && next build && rm -rf .next/cache .next/dev .next/diagnostics .next/trace .next/trace-build .next/turbopack"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"better-sqlite3": "^12.10.0",
|
|
35
|
+
"next": "16.2.6",
|
|
36
|
+
"react": "19.2.4",
|
|
37
|
+
"react-dom": "19.2.4",
|
|
38
|
+
"zod": "^4.4.3"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@tailwindcss/postcss": "^4",
|
|
42
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
43
|
+
"@types/node": "^20",
|
|
44
|
+
"@types/react": "^19",
|
|
45
|
+
"@types/react-dom": "^19",
|
|
46
|
+
"eslint": "^9",
|
|
47
|
+
"eslint-config-next": "16.2.6",
|
|
48
|
+
"tailwindcss": "^4",
|
|
49
|
+
"typescript": "^5"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/public/file.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
package/public/globe.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
package/public/next.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|