@jlongo78/agent-spaces 0.9.8 → 0.9.9

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.
Files changed (356) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +3 -0
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +23 -0
  6. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/(desktop)/cortex/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/(desktop)/terminal/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  23. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  24. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  30. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  31. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  32. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  33. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  34. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  35. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  36. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  38. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  39. package/.next/standalone/.next/server/app/admin/analytics.rsc +3 -3
  40. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
  41. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  42. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  43. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  44. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +3 -3
  45. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  46. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +2 -2
  47. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  48. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  49. package/.next/standalone/.next/server/app/admin/users.rsc +2 -2
  50. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +1 -1
  51. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  52. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  53. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  54. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +2 -2
  57. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  58. package/.next/standalone/.next/server/app/analytics.html +1 -1
  59. package/.next/standalone/.next/server/app/analytics.rsc +2 -2
  60. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +1 -1
  61. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  62. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  63. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +2 -2
  64. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  65. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +2 -2
  66. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  67. package/.next/standalone/.next/server/app/api/claude/usage/route/app-paths-manifest.json +3 -0
  68. package/.next/standalone/.next/server/app/api/claude/usage/route/build-manifest.json +11 -0
  69. package/.next/standalone/.next/server/app/api/claude/usage/route/server-reference-manifest.json +4 -0
  70. package/.next/standalone/.next/server/app/api/claude/usage/route.js +8 -0
  71. package/.next/standalone/.next/server/app/api/claude/usage/route.js.map +5 -0
  72. package/.next/standalone/.next/server/app/api/claude/usage/route.js.nft.json +1 -0
  73. package/.next/standalone/.next/server/app/api/claude/usage/route_client-reference-manifest.js +2 -0
  74. package/.next/standalone/.next/server/app/api/whisper/route.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/app-paths-manifest.json +3 -0
  76. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/build-manifest.json +11 -0
  77. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/server-reference-manifest.json +4 -0
  78. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js +8 -0
  79. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js.map +5 -0
  80. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js.nft.json +1 -0
  81. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route_client-reference-manifest.js +2 -0
  82. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/app-paths-manifest.json +3 -0
  83. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/build-manifest.json +11 -0
  84. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/server-reference-manifest.json +4 -0
  85. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js +8 -0
  86. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js.map +5 -0
  87. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js.nft.json +1 -0
  88. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route_client-reference-manifest.js +2 -0
  89. package/.next/standalone/.next/server/app/cortex.html +1 -1
  90. package/.next/standalone/.next/server/app/cortex.rsc +2 -2
  91. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +1 -1
  92. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  93. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  94. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +2 -2
  95. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  96. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  97. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  98. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/login.html +1 -1
  100. package/.next/standalone/.next/server/app/login.rsc +2 -2
  101. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  102. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  103. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  104. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  105. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  106. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  107. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  108. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  109. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  110. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  111. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  112. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  113. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  114. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  115. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  116. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  117. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  118. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  119. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  121. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  122. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  123. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  124. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  125. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  126. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  127. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  128. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  129. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  130. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  131. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  132. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  133. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  134. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  135. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  136. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  137. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  138. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  139. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  141. package/.next/standalone/.next/server/app/m/terminal.rsc +2 -2
  142. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +2 -2
  143. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  144. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  145. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  146. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +1 -1
  147. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  148. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  149. package/.next/standalone/.next/server/app/m.html +1 -1
  150. package/.next/standalone/.next/server/app/m.rsc +2 -2
  151. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  152. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  153. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  154. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  155. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  156. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  157. package/.next/standalone/.next/server/app/network.html +1 -1
  158. package/.next/standalone/.next/server/app/network.rsc +2 -2
  159. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  160. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  161. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  162. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  164. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  165. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  166. package/.next/standalone/.next/server/app/projects.html +1 -1
  167. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  168. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  169. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  170. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  171. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  172. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  173. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  174. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  175. package/.next/standalone/.next/server/app/sessions.html +1 -1
  176. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  177. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  178. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  179. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  180. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  181. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  182. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  183. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  184. package/.next/standalone/.next/server/app/settings.html +1 -1
  185. package/.next/standalone/.next/server/app/settings.rsc +3 -3
  186. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +2 -2
  187. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  188. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  189. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  190. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  191. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  192. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  193. package/.next/standalone/.next/server/app/terminal.html +1 -1
  194. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  195. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  196. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  197. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  198. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  199. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  200. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  201. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  202. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +1 -1
  203. package/.next/standalone/.next/server/app/vr.html +1 -1
  204. package/.next/standalone/.next/server/app/vr.rsc +2 -2
  205. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +2 -2
  206. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +1 -1
  207. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +2 -2
  208. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +2 -2
  209. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +1 -1
  210. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +1 -1
  211. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  212. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  213. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  214. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  215. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  216. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  217. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  218. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  219. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  220. package/.next/standalone/.next/server/app-paths-manifest.json +3 -0
  221. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00e90fc6._.js +15 -2
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01ab8675._.js +15 -2
  223. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03974f05._.js +15 -2
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__046c9b91._.js +15 -2
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04ae6bf0._.js +15 -2
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__056fa416._.js +1 -1
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ac4ea3f._.js +1 -1
  228. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b8e64cb._.js +15 -2
  229. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0facd39e._.js +15 -2
  230. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10bc76a3._.js +1 -1
  231. package/.next/standalone/.next/server/chunks/[root-of-the-server]__115f3934._.js +15 -2
  232. package/.next/standalone/.next/server/chunks/[root-of-the-server]__11f155f1._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/[root-of-the-server]__160e7c73._.js +52 -24
  234. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17a3b966._.js +15 -2
  235. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17d3a2b2._.js +15 -2
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a86c055._.js +15 -2
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20b5e9c4._.js +1 -1
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28d6fbd8._.js +15 -2
  239. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a3f866b._.js +16 -3
  240. package/.next/standalone/.next/server/chunks/[root-of-the-server]__316617e7._.js +2 -2
  241. package/.next/standalone/.next/server/chunks/[root-of-the-server]__32ad8f71._.js +15 -2
  242. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35457394._.js +15 -2
  243. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35de78e6._.js +15 -2
  244. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3685ffcb._.js +15 -2
  245. package/.next/standalone/.next/server/chunks/[root-of-the-server]__38954988._.js +15 -2
  246. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3a32b624._.js +111 -0
  247. package/.next/standalone/.next/server/chunks/[root-of-the-server]__426ad936._.js +17 -4
  248. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4985c034._.js +15 -2
  249. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c6ce9ed._.js +16 -3
  250. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5cebe58a._.js +15 -2
  251. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5d5e4789._.js +15 -2
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__65676930._.js +1 -1
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__67cab326._.js +2 -2
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__698c6f01._.js +16 -3
  255. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c64af29._.js +22 -9
  256. package/.next/standalone/.next/server/chunks/[root-of-the-server]__73aed9f5._.js +15 -2
  257. package/.next/standalone/.next/server/chunks/[root-of-the-server]__79b6a9bb._.js +15 -2
  258. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7db704c6._.js +17 -4
  259. package/.next/standalone/.next/server/chunks/[root-of-the-server]__812ca02b._.js +15 -2
  260. package/.next/standalone/.next/server/chunks/[root-of-the-server]__821f50fa._.js +15 -2
  261. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8716b86e._.js +15 -2
  262. package/.next/standalone/.next/server/chunks/[root-of-the-server]__884ef754._.js +15 -2
  263. package/.next/standalone/.next/server/chunks/[root-of-the-server]__88cdbd68._.js +15 -2
  264. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89d9aba9._.js +15 -2
  265. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8c2e1260._.js +111 -0
  266. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d536cb5._.js +15 -2
  267. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8df8c5d1._.js +15 -2
  268. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8f2ccc41._.js +15 -2
  269. package/.next/standalone/.next/server/chunks/[root-of-the-server]__95c9d682._.js +15 -2
  270. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e5d7774._.js +15 -2
  271. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9edcff87._.js +15 -2
  272. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a049dfc2._.js +15 -2
  273. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a5b4bb9a._.js +16 -3
  274. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a83262a1._.js +15 -2
  275. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9cd1240._.js +15 -2
  276. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d7f822._.js +15 -2
  277. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad08c221._.js +15 -2
  278. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad585f2f._.js +15 -2
  279. package/.next/standalone/.next/server/chunks/[root-of-the-server]__afcb8f7d._.js +15 -2
  280. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bc250d43._.js +15 -2
  281. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bce2a6e7._.js +15 -2
  282. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c011bf91._.js +15 -2
  283. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c37d6380._.js +1 -1
  284. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cae392eb._.js +15 -2
  285. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cc2616bb._.js +16 -3
  286. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d501fa9b._.js +15 -2
  287. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d59c6c15._.js +16 -3
  288. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d5c1db32._.js +15 -2
  289. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dba60c86._.js +15 -2
  290. package/.next/standalone/.next/server/chunks/[root-of-the-server]__de14b9ae._.js +15 -2
  291. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e10643d1._.js +15 -2
  292. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e2a996e5._.js +23 -10
  293. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3477417._.js +15 -2
  294. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e4db362e._.js +1 -1
  295. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e4e70b86._.js +15 -2
  296. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e54925af._.js +15 -2
  297. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8cbeaca._.js +111 -0
  298. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8edc5b0._.js +15 -2
  299. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eab4d83b._.js +15 -2
  300. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ead29015._.js +1 -1
  301. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f056fd83._.js +15 -2
  302. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f0e99572._.js +15 -2
  303. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fe1e16d0._.js +15 -2
  304. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff9cd277._.js +15 -2
  305. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ffaea2ce._.js +15 -2
  306. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_claude_usage_route_actions_fe002ec1.js +3 -0
  307. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_workspaces_[id]_todos_route_actions_0d4ffac5.js +3 -0
  308. package/.next/standalone/.next/server/chunks/ce889_server_app_api_workspaces_[id]_todos_[todoId]_route_actions_754fe6b9.js +3 -0
  309. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  310. package/.next/standalone/.next/server/chunks/ssr/{_17b946fd._.js → _20c2cf3a._.js} +2 -2
  311. package/.next/standalone/.next/server/chunks/ssr/_5f55bf8f._.js +3 -0
  312. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_settings_page_tsx_f74824b3._.js +1 -1
  313. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_terminal_page_tsx_de5e8d85._.js +1 -1
  314. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__90eeddae._.js +1 -1
  315. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  316. package/.next/standalone/.next/server/pages/404.html +1 -1
  317. package/.next/standalone/.next/server/pages/500.html +2 -2
  318. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  319. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  320. package/.next/standalone/.next/static/chunks/14216197f9dcbe5b.css +3 -0
  321. package/.next/standalone/.next/static/chunks/{0852575eb90c1e8d.js → 4c9fb0a38f041a3d.js} +2 -2
  322. package/.next/standalone/.next/static/chunks/8f6f93ab45a5ff5b.js +1 -0
  323. package/.next/standalone/.next/static/chunks/{e62bb488d02db247.js → d2566c2dcf53fef3.js} +1 -1
  324. package/.next/standalone/.next/static/chunks/{7f6a14f1849fa94d.js → ff7d85dade44d1f3.js} +1 -1
  325. package/.next/standalone/cortex-hook-debug.log +61 -0
  326. package/.next/standalone/docs/features/claude-usage.md +105 -0
  327. package/.next/standalone/docs/features/workspace-todos.md +127 -0
  328. package/.next/standalone/docs/superpowers/plans/2026-04-21-workspace-todos.md +1097 -0
  329. package/.next/standalone/docs/superpowers/plans/2026-04-22-claude-usage-display.md +749 -0
  330. package/.next/standalone/docs/superpowers/specs/2026-04-21-workspace-todos-design.md +180 -0
  331. package/.next/standalone/docs/superpowers/specs/2026-04-22-claude-usage-display-design.md +183 -0
  332. package/.next/standalone/package-lock.json +2 -2
  333. package/.next/standalone/package.json +1 -1
  334. package/.next/standalone/src/app/(desktop)/settings/page.tsx +40 -1
  335. package/.next/standalone/src/app/(desktop)/terminal/page.tsx +54 -2
  336. package/.next/standalone/src/app/api/claude/usage/route.ts +33 -0
  337. package/.next/standalone/src/app/api/config/route.ts +3 -0
  338. package/.next/standalone/src/app/api/workspaces/[id]/todos/[todoId]/route.ts +55 -0
  339. package/.next/standalone/src/app/api/workspaces/[id]/todos/route.ts +43 -0
  340. package/.next/standalone/src/components/claude/claude-usage-strip.tsx +175 -0
  341. package/.next/standalone/src/components/workspace/workspace-todos.tsx +265 -0
  342. package/.next/standalone/src/hooks/use-claude-usage.ts +66 -0
  343. package/.next/standalone/src/lib/claude/credentials.ts +36 -0
  344. package/.next/standalone/src/lib/claude/usage.ts +69 -0
  345. package/.next/standalone/src/lib/config.ts +3 -0
  346. package/.next/standalone/src/lib/db/queries.ts +103 -1
  347. package/.next/standalone/src/lib/db/schema.ts +18 -0
  348. package/.next/standalone/src/types/claude.ts +39 -0
  349. package/.next/standalone/tests/db/workspace-todos.test.ts +156 -0
  350. package/package.json +1 -1
  351. package/.next/standalone/.next/server/chunks/ssr/_3ba93bdd._.js +0 -3
  352. package/.next/standalone/.next/static/chunks/074df89a63b6a854.js +0 -1
  353. package/.next/standalone/.next/static/chunks/2b769d1597e4fc1c.css +0 -3
  354. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → bAQs2gDlFrq3e8w9ni9tr}/_buildManifest.js +0 -0
  355. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → bAQs2gDlFrq3e8w9ni9tr}/_clientMiddlewareManifest.json +0 -0
  356. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → bAQs2gDlFrq3e8w9ni9tr}/_ssgManifest.js +0 -0
@@ -0,0 +1,749 @@
1
+ # Claude Usage Display Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Show a compact Anthropic plan-usage readout (mirroring `/usage` in Claude Code) in the Spaces terminal page header, visible when the active workspace has at least one Claude pane.
6
+
7
+ **Architecture:** Spaces reads the OAuth access token from `~/.claude/.credentials.json` (already maintained by Claude Code), calls `https://api.anthropic.com/api/oauth/usage`, caches 30s server-side, and polls the route every 60s from a React hook. A three-bar strip component renders in the header; clicking expands a popover with all windows. Passive refresh: if the access token is expired or missing, the strip shows a "sign in via Claude Code" hint.
8
+
9
+ **Tech Stack:** Next.js App Router, React 18 client components, Node `fetch` with `AbortController`, TypeScript, Tailwind, lucide-react.
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-04-22-claude-usage-display-design.md`
12
+
13
+ **Repo workflow note:** Commit directly to `main`. No feature branch, no PR. Each task ends with a commit.
14
+
15
+ ---
16
+
17
+ ## File Structure
18
+
19
+ **Create:**
20
+ - `src/lib/claude/credentials.ts` — reads `.credentials.json`, extracts and validates the `claudeAiOauth` block.
21
+ - `src/lib/claude/usage.ts` — calls Anthropic's `/api/oauth/usage`, caches 30s.
22
+ - `src/app/api/claude/usage/route.ts` — `GET` handler wiring the above together.
23
+ - `src/hooks/use-claude-usage.ts` — 60s polling hook.
24
+ - `src/components/claude/claude-usage-strip.tsx` — compact 3-bar strip + expanded popover.
25
+ - `docs/features/claude-usage.md` — feature doc.
26
+
27
+ **Modify:**
28
+ - `src/types/claude.ts` — add `RateLimit`, `ExtraUsage`, `Utilization`, `UsageResponse` types.
29
+ - `src/app/(desktop)/terminal/page.tsx` — mount `<ClaudeUsageStrip>` conditionally in the header.
30
+
31
+ ---
32
+
33
+ ## Task 1: Types + credentials reader
34
+
35
+ **Files:**
36
+ - Modify: `src/types/claude.ts`
37
+ - Create: `src/lib/claude/credentials.ts`
38
+
39
+ - [ ] **Step 1: Add types to `src/types/claude.ts`**
40
+
41
+ Append at the end of the file:
42
+
43
+ ```ts
44
+ // ─── Claude plan-usage (mirrors /usage in Claude Code) ───────
45
+
46
+ export interface RateLimit {
47
+ utilization: number | null; // 0-100
48
+ resets_at: string | null; // ISO 8601
49
+ }
50
+
51
+ export interface ExtraUsage {
52
+ is_enabled: boolean;
53
+ monthly_limit: number | null;
54
+ used_credits: number | null;
55
+ utilization: number | null;
56
+ }
57
+
58
+ export interface Utilization {
59
+ five_hour?: RateLimit | null;
60
+ seven_day?: RateLimit | null;
61
+ seven_day_oauth_apps?: RateLimit | null;
62
+ seven_day_opus?: RateLimit | null;
63
+ seven_day_sonnet?: RateLimit | null;
64
+ extra_usage?: ExtraUsage | null;
65
+ }
66
+
67
+ export type UsageResponse =
68
+ | { status: 'ok'; data: Utilization }
69
+ | { status: 'unauthenticated' }
70
+ | { status: 'expired' }
71
+ | { status: 'upstream_error' };
72
+ ```
73
+
74
+ - [ ] **Step 2: Create `src/lib/claude/credentials.ts`**
75
+
76
+ ```ts
77
+ import path from 'path';
78
+ import os from 'os';
79
+ import { readFile } from 'fs/promises';
80
+
81
+ export interface ClaudeAiOAuthTokens {
82
+ accessToken: string;
83
+ refreshToken: string | null;
84
+ expiresAt: number | null; // epoch ms
85
+ scopes?: string[];
86
+ }
87
+
88
+ function getCredentialsPath(): string {
89
+ const home = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
90
+ return path.join(home, '.credentials.json');
91
+ }
92
+
93
+ /**
94
+ * Reads ~/.claude/.credentials.json and returns the claudeAiOauth block.
95
+ * Returns null on any read/parse failure or if the block is absent.
96
+ */
97
+ export async function readClaudeAiOauthTokens(): Promise<ClaudeAiOAuthTokens | null> {
98
+ try {
99
+ const raw = await readFile(getCredentialsPath(), 'utf8');
100
+ const parsed = JSON.parse(raw) as { claudeAiOauth?: ClaudeAiOAuthTokens };
101
+ const tokens = parsed.claudeAiOauth;
102
+ if (!tokens?.accessToken) return null;
103
+ return tokens;
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+
109
+ export function isTokenExpired(tokens: ClaudeAiOAuthTokens, nowMs = Date.now()): boolean {
110
+ if (!tokens.expiresAt) return false; // no expiry set → treat as valid
111
+ return nowMs >= tokens.expiresAt;
112
+ }
113
+ ```
114
+
115
+ - [ ] **Step 3: Type-check**
116
+
117
+ ```bash
118
+ cd /home/jlongo/development/spaces && npx tsc --noEmit
119
+ ```
120
+
121
+ Expected: no new errors.
122
+
123
+ - [ ] **Step 4: Commit**
124
+
125
+ ```bash
126
+ cd /home/jlongo/development/spaces
127
+ git add src/types/claude.ts src/lib/claude/credentials.ts
128
+ git commit -m "feat(claude): read OAuth tokens from .credentials.json"
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Task 2: Anthropic usage fetcher + cache
134
+
135
+ **Files:**
136
+ - Create: `src/lib/claude/usage.ts`
137
+
138
+ - [ ] **Step 1: Create the fetcher**
139
+
140
+ ```ts
141
+ import type { Utilization } from '@/types/claude';
142
+
143
+ const ANTHROPIC_USAGE_URL = 'https://api.anthropic.com/api/oauth/usage';
144
+ const REQUEST_TIMEOUT_MS = 5_000;
145
+ const CACHE_TTL_MS = 30_000;
146
+
147
+ // UA matches the Claude Code format because Anthropic's endpoint classifies
148
+ // the caller by UA. Kept in sync manually if upstream ever changes.
149
+ const USER_AGENT = 'claude-code/spaces-integration';
150
+
151
+ interface CacheEntry {
152
+ fetchedAt: number;
153
+ data: Utilization;
154
+ }
155
+
156
+ const cache = new Map<string, CacheEntry>();
157
+
158
+ function cacheKey(accessToken: string): string {
159
+ return accessToken.slice(0, 16);
160
+ }
161
+
162
+ export type FetchOutcome =
163
+ | { ok: true; data: Utilization }
164
+ | { ok: false; reason: 'upstream_error' };
165
+
166
+ export async function fetchUtilization(accessToken: string): Promise<FetchOutcome> {
167
+ const key = cacheKey(accessToken);
168
+ const cached = cache.get(key);
169
+ if (cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS) {
170
+ return { ok: true, data: cached.data };
171
+ }
172
+
173
+ const controller = new AbortController();
174
+ const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
175
+
176
+ try {
177
+ const res = await fetch(ANTHROPIC_USAGE_URL, {
178
+ method: 'GET',
179
+ headers: {
180
+ 'Authorization': `Bearer ${accessToken}`,
181
+ 'Content-Type': 'application/json',
182
+ 'User-Agent': USER_AGENT,
183
+ },
184
+ signal: controller.signal,
185
+ });
186
+
187
+ if (!res.ok) {
188
+ return { ok: false, reason: 'upstream_error' };
189
+ }
190
+
191
+ const data = (await res.json()) as Utilization;
192
+ cache.set(key, { fetchedAt: Date.now(), data });
193
+ return { ok: true, data };
194
+ } catch {
195
+ return { ok: false, reason: 'upstream_error' };
196
+ } finally {
197
+ clearTimeout(timer);
198
+ }
199
+ }
200
+
201
+ /** Testing/hot-reload helper. */
202
+ export function __clearUsageCache() {
203
+ cache.clear();
204
+ }
205
+ ```
206
+
207
+ - [ ] **Step 2: Type-check**
208
+
209
+ ```bash
210
+ cd /home/jlongo/development/spaces && npx tsc --noEmit
211
+ ```
212
+
213
+ Expected: no new errors.
214
+
215
+ - [ ] **Step 3: Commit**
216
+
217
+ ```bash
218
+ cd /home/jlongo/development/spaces
219
+ git add src/lib/claude/usage.ts
220
+ git commit -m "feat(claude): fetch Anthropic plan-usage with 30s cache"
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Task 3: API route `GET /api/claude/usage`
226
+
227
+ **Files:**
228
+ - Create: `src/app/api/claude/usage/route.ts`
229
+
230
+ - [ ] **Step 1: Create the route**
231
+
232
+ ```ts
233
+ import { NextRequest, NextResponse } from 'next/server';
234
+ import { getAuthUser, withUser } from '@/lib/auth';
235
+ import { ensureInitialized } from '@/lib/db/init';
236
+ import { readClaudeAiOauthTokens, isTokenExpired } from '@/lib/claude/credentials';
237
+ import { fetchUtilization } from '@/lib/claude/usage';
238
+ import type { UsageResponse } from '@/types/claude';
239
+
240
+ export async function GET(request: NextRequest) {
241
+ const user = getAuthUser(request);
242
+ return withUser(user, async () => {
243
+ await ensureInitialized();
244
+
245
+ const tokens = await readClaudeAiOauthTokens();
246
+ if (!tokens) {
247
+ const body: UsageResponse = { status: 'unauthenticated' };
248
+ return NextResponse.json(body);
249
+ }
250
+
251
+ if (isTokenExpired(tokens)) {
252
+ const body: UsageResponse = { status: 'expired' };
253
+ return NextResponse.json(body);
254
+ }
255
+
256
+ const outcome = await fetchUtilization(tokens.accessToken);
257
+ if (!outcome.ok) {
258
+ const body: UsageResponse = { status: 'upstream_error' };
259
+ return NextResponse.json(body);
260
+ }
261
+
262
+ const body: UsageResponse = { status: 'ok', data: outcome.data };
263
+ return NextResponse.json(body);
264
+ });
265
+ }
266
+ ```
267
+
268
+ - [ ] **Step 2: Smoke test against the running dev server**
269
+
270
+ Determine which dev server is listening (3458 for turbopack is typical; 3457 for production build):
271
+
272
+ ```bash
273
+ curl -sS http://localhost:3458/api/workspaces -o /dev/null -w '%{http_code}\n' 2>/dev/null
274
+ curl -sS http://localhost:3457/api/workspaces -o /dev/null -w '%{http_code}\n' 2>/dev/null
275
+ ```
276
+
277
+ Use whichever returns `200`. Then:
278
+
279
+ ```bash
280
+ BASE=http://localhost:3458
281
+ curl -s "$BASE/api/claude/usage"
282
+ ```
283
+
284
+ Expected: JSON with one of the four statuses. If you're logged in, it should be `{"status":"ok","data":{...}}` with `five_hour`, `seven_day_opus`, etc. If logged out or no credentials file, it should be `{"status":"unauthenticated"}`.
285
+
286
+ Don't start a new dev server; use whatever is already running. If the only listener is a production build that won't hot-reload, report BLOCKED.
287
+
288
+ - [ ] **Step 3: Commit**
289
+
290
+ ```bash
291
+ cd /home/jlongo/development/spaces
292
+ git add src/app/api/claude/usage/route.ts
293
+ git commit -m "feat(api): add GET /api/claude/usage"
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Task 4: `useClaudeUsage` hook
299
+
300
+ **Files:**
301
+ - Create: `src/hooks/use-claude-usage.ts`
302
+
303
+ - [ ] **Step 1: Create the hook**
304
+
305
+ ```ts
306
+ 'use client';
307
+
308
+ import { useEffect, useState } from 'react';
309
+ import { api } from '@/lib/api';
310
+ import type { UsageResponse } from '@/types/claude';
311
+
312
+ const POLL_INTERVAL_MS = 60_000;
313
+
314
+ export function useClaudeUsage(enabled: boolean): UsageResponse | null {
315
+ const [response, setResponse] = useState<UsageResponse | null>(null);
316
+
317
+ useEffect(() => {
318
+ if (!enabled) {
319
+ setResponse(null);
320
+ return;
321
+ }
322
+
323
+ let cancelled = false;
324
+
325
+ async function load() {
326
+ try {
327
+ const res = await fetch(api('/api/claude/usage'));
328
+ if (!res.ok) return;
329
+ const data: UsageResponse = await res.json();
330
+ if (!cancelled) setResponse(data);
331
+ } catch {
332
+ // Silent — the UI handles undefined state gracefully.
333
+ }
334
+ }
335
+
336
+ load();
337
+ const timer = setInterval(load, POLL_INTERVAL_MS);
338
+
339
+ return () => {
340
+ cancelled = true;
341
+ clearInterval(timer);
342
+ };
343
+ }, [enabled]);
344
+
345
+ return response;
346
+ }
347
+ ```
348
+
349
+ - [ ] **Step 2: Type-check**
350
+
351
+ ```bash
352
+ cd /home/jlongo/development/spaces && npx tsc --noEmit
353
+ ```
354
+
355
+ Expected: no new errors.
356
+
357
+ - [ ] **Step 3: Commit**
358
+
359
+ ```bash
360
+ cd /home/jlongo/development/spaces
361
+ git add src/hooks/use-claude-usage.ts
362
+ git commit -m "feat(hooks): add useClaudeUsage polling hook"
363
+ ```
364
+
365
+ ---
366
+
367
+ ## Task 5: `<ClaudeUsageStrip />` component
368
+
369
+ **Files:**
370
+ - Create: `src/components/claude/claude-usage-strip.tsx`
371
+
372
+ - [ ] **Step 1: Create the component**
373
+
374
+ ```tsx
375
+ 'use client';
376
+
377
+ import { useEffect, useRef, useState } from 'react';
378
+ import { Zap, LogIn } from 'lucide-react';
379
+ import { useClaudeUsage } from '@/hooks/use-claude-usage';
380
+ import type { RateLimit } from '@/types/claude';
381
+
382
+ interface Props {
383
+ enabled: boolean;
384
+ }
385
+
386
+ function utilizationColor(pct: number | null): string {
387
+ if (pct == null) return '#52525b'; // zinc-600 — unknown
388
+ if (pct <= 70) return '#22c55e'; // green-500
389
+ if (pct <= 90) return '#f59e0b'; // amber-500
390
+ return '#ef4444'; // red-500
391
+ }
392
+
393
+ function formatReset(resetsAt: string | null): string {
394
+ if (!resetsAt) return '';
395
+ const ms = new Date(resetsAt).getTime() - Date.now();
396
+ if (ms <= 0) return 'now';
397
+ const h = Math.floor(ms / 3_600_000);
398
+ const m = Math.floor((ms % 3_600_000) / 60_000);
399
+ if (h >= 24) {
400
+ const d = Math.floor(h / 24);
401
+ const rh = h - d * 24;
402
+ return `${d}d ${rh}h`;
403
+ }
404
+ if (h > 0) return `${h}h ${m}m`;
405
+ return `${m}m`;
406
+ }
407
+
408
+ function Bar({ label, limit }: { label: string; limit: RateLimit | null | undefined }) {
409
+ if (!limit || limit.utilization == null) return null;
410
+ const pct = Math.min(100, Math.max(0, limit.utilization));
411
+ const color = utilizationColor(pct);
412
+ const reset = formatReset(limit.resets_at);
413
+ return (
414
+ <div
415
+ className="flex items-center gap-1.5 text-[10px]"
416
+ title={reset ? `${label}: ${Math.floor(pct)}% used · resets in ${reset}` : `${label}: ${Math.floor(pct)}% used`}
417
+ >
418
+ <span className="text-zinc-400 font-medium">{label}</span>
419
+ <div className="w-12 h-1 bg-zinc-800 rounded-full overflow-hidden">
420
+ <div
421
+ className="h-full transition-all"
422
+ style={{ width: `${pct}%`, backgroundColor: color }}
423
+ />
424
+ </div>
425
+ <span className="text-zinc-500 tabular-nums w-7 text-right">{Math.floor(pct)}%</span>
426
+ </div>
427
+ );
428
+ }
429
+
430
+ export function ClaudeUsageStrip({ enabled }: Props) {
431
+ const response = useClaudeUsage(enabled);
432
+ const [expanded, setExpanded] = useState(false);
433
+ const popoverRef = useRef<HTMLDivElement>(null);
434
+
435
+ useEffect(() => {
436
+ if (!expanded) return;
437
+ function handleClick(e: MouseEvent) {
438
+ if (popoverRef.current && !popoverRef.current.contains(e.target as Node)) {
439
+ setExpanded(false);
440
+ }
441
+ }
442
+ document.addEventListener('mousedown', handleClick);
443
+ return () => document.removeEventListener('mousedown', handleClick);
444
+ }, [expanded]);
445
+
446
+ if (!enabled || !response) return null;
447
+
448
+ if (response.status === 'unauthenticated' || response.status === 'expired') {
449
+ return (
450
+ <div
451
+ className="flex items-center gap-1.5 px-2 py-1 text-[10px] text-zinc-500 border border-zinc-800 rounded-md"
452
+ title={response.status === 'expired' ? 'OAuth token expired — run any Claude Code command to refresh' : 'No Claude.ai credentials found'}
453
+ >
454
+ <LogIn className="w-3 h-3" />
455
+ sign in via Claude Code
456
+ </div>
457
+ );
458
+ }
459
+
460
+ if (response.status === 'upstream_error') {
461
+ return null; // Silent — per spec.
462
+ }
463
+
464
+ const { data } = response;
465
+ const extra = data.extra_usage;
466
+ const hasOverage = !!(extra?.is_enabled && extra?.used_credits && extra.used_credits > 0);
467
+
468
+ return (
469
+ <div className="relative">
470
+ <button
471
+ onClick={() => setExpanded(v => !v)}
472
+ className="flex items-center gap-2.5 px-2.5 py-1 border border-zinc-800 rounded-md hover:border-zinc-700 transition-colors"
473
+ title="Click for full usage detail"
474
+ >
475
+ <Zap className="w-3 h-3 text-amber-400" />
476
+ <Bar label="5h" limit={data.five_hour} />
477
+ <Bar label="Opus" limit={data.seven_day_opus} />
478
+ <Bar label="Sonnet" limit={data.seven_day_sonnet} />
479
+ {hasOverage && extra?.used_credits != null && (
480
+ <span className="text-[10px] text-amber-400 border-l border-zinc-800 pl-2">
481
+ +${extra.used_credits.toFixed(2)} overage
482
+ </span>
483
+ )}
484
+ </button>
485
+
486
+ {expanded && (
487
+ <div
488
+ ref={popoverRef}
489
+ className="absolute top-full right-0 mt-1.5 z-50 w-80 p-3 bg-zinc-900 border border-zinc-700 rounded-md shadow-xl"
490
+ >
491
+ <div className="text-[10px] uppercase tracking-wider text-zinc-500 font-medium mb-2">
492
+ Plan Usage
493
+ </div>
494
+ <div className="space-y-2">
495
+ <ExpandedRow label="5-hour window" limit={data.five_hour} />
496
+ <ExpandedRow label="7-day (overall)" limit={data.seven_day} />
497
+ <ExpandedRow label="7-day · Opus" limit={data.seven_day_opus} />
498
+ <ExpandedRow label="7-day · Sonnet" limit={data.seven_day_sonnet} />
499
+ <ExpandedRow label="7-day · OAuth apps" limit={data.seven_day_oauth_apps} />
500
+ </div>
501
+ {extra?.is_enabled && (
502
+ <div className="mt-3 pt-3 border-t border-zinc-800">
503
+ <div className="text-[10px] uppercase tracking-wider text-zinc-500 font-medium mb-1.5">
504
+ Overage credits
505
+ </div>
506
+ <div className="text-xs text-zinc-300">
507
+ {extra.used_credits != null ? `$${extra.used_credits.toFixed(2)}` : '—'}
508
+ {extra.monthly_limit != null && (
509
+ <span className="text-zinc-500"> / ${extra.monthly_limit.toFixed(2)} monthly</span>
510
+ )}
511
+ </div>
512
+ </div>
513
+ )}
514
+ </div>
515
+ )}
516
+ </div>
517
+ );
518
+ }
519
+
520
+ function ExpandedRow({ label, limit }: { label: string; limit: RateLimit | null | undefined }) {
521
+ if (!limit || limit.utilization == null) {
522
+ return (
523
+ <div className="flex items-center justify-between text-xs">
524
+ <span className="text-zinc-400">{label}</span>
525
+ <span className="text-zinc-600">—</span>
526
+ </div>
527
+ );
528
+ }
529
+ const pct = Math.min(100, Math.max(0, limit.utilization));
530
+ const color = utilizationColor(pct);
531
+ const reset = formatReset(limit.resets_at);
532
+ return (
533
+ <div>
534
+ <div className="flex items-center justify-between text-xs mb-1">
535
+ <span className="text-zinc-300">{label}</span>
536
+ <span className="text-zinc-500 tabular-nums">
537
+ {Math.floor(pct)}%{reset && <span className="ml-1.5 text-zinc-600">· {reset}</span>}
538
+ </span>
539
+ </div>
540
+ <div className="h-1.5 bg-zinc-800 rounded-full overflow-hidden">
541
+ <div
542
+ className="h-full transition-all"
543
+ style={{ width: `${pct}%`, backgroundColor: color }}
544
+ />
545
+ </div>
546
+ </div>
547
+ );
548
+ }
549
+ ```
550
+
551
+ - [ ] **Step 2: Type-check**
552
+
553
+ ```bash
554
+ cd /home/jlongo/development/spaces && npx tsc --noEmit
555
+ ```
556
+
557
+ - [ ] **Step 3: Commit**
558
+
559
+ ```bash
560
+ cd /home/jlongo/development/spaces
561
+ git add src/components/claude/claude-usage-strip.tsx
562
+ git commit -m "feat(ui): add ClaudeUsageStrip component"
563
+ ```
564
+
565
+ ---
566
+
567
+ ## Task 6: Mount `<ClaudeUsageStrip />` in the terminal header
568
+
569
+ **Files:**
570
+ - Modify: `src/app/(desktop)/terminal/page.tsx`
571
+
572
+ - [ ] **Step 1: Add the import**
573
+
574
+ At the top of `src/app/(desktop)/terminal/page.tsx`, near the other component imports (around the `WorkspaceTodos` / `ProjectWizard` imports), add:
575
+
576
+ ```tsx
577
+ import { ClaudeUsageStrip } from '@/components/claude/claude-usage-strip';
578
+ ```
579
+
580
+ - [ ] **Step 2: Mount conditionally in the header**
581
+
582
+ Find the header's right-hand button cluster — the `<div className="flex items-center gap-2">` that contains the `Files`, `Collab`, `Close`, and `Add Pane` buttons (around lines 863-922, inside the entered-workspace `return`). Insert the strip **as the first child** of that cluster, before the `Files` button:
583
+
584
+ ```tsx
585
+ <div className="flex items-center gap-2">
586
+ <ClaudeUsageStrip enabled={panes.some(p => p.agentType === 'claude' && !poppedOut.has(p.id))} />
587
+ <button
588
+ onClick={() => setShowFiles(!showFiles)}
589
+ ...
590
+ ```
591
+
592
+ The `enabled` prop is `true` when the current workspace has at least one visible (not popped-out) Claude pane. `panes` is already in scope in `TerminalPageInner`.
593
+
594
+ - [ ] **Step 3: Type-check**
595
+
596
+ ```bash
597
+ cd /home/jlongo/development/spaces && npx tsc --noEmit
598
+ ```
599
+
600
+ - [ ] **Step 4: Commit**
601
+
602
+ ```bash
603
+ cd /home/jlongo/development/spaces
604
+ git add "src/app/(desktop)/terminal/page.tsx"
605
+ git commit -m "feat(terminal): mount ClaudeUsageStrip in header when Claude panes exist"
606
+ ```
607
+
608
+ ---
609
+
610
+ ## Task 7: Feature doc
611
+
612
+ **Files:**
613
+ - Create: `docs/features/claude-usage.md`
614
+
615
+ - [ ] **Step 1: Write the doc**
616
+
617
+ ```markdown
618
+ # Claude Plan-Usage Display
619
+
620
+ **Status:** stable
621
+ **Owner:** jlongo
622
+ **Last updated:** 2026-04-22
623
+
624
+ ## Overview
625
+
626
+ A compact readout of the user's Anthropic plan-usage rate limits, surfaced in the terminal page header whenever the active workspace has at least one Claude pane. Shows 5-hour, 7-day Opus, and 7-day Sonnet windows at a glance; click expands to all windows plus overage credits. Data matches what `/usage` shows inside Claude Code.
627
+
628
+ ## User-facing behavior
629
+
630
+ - Open any workspace on `/terminal` that has a Claude pane.
631
+ - A horizontal strip appears in the header (right side, before Files / Collab / Close / Add Pane).
632
+ - Three thin progress bars: **5h**, **Opus**, **Sonnet** — each with a percent label and a color that escalates green → amber → red.
633
+ - Hover a bar → tooltip `{label}: X% used · resets in 2h 14m`.
634
+ - Click the strip → popover with all five rate-limit windows + an overage-credits block if the account has overage enabled.
635
+ - If the OAuth token is missing or expired, the strip shows `sign in via Claude Code` with a small login icon. No auto-refresh.
636
+ - If the Anthropic endpoint fails or times out, the strip hides silently.
637
+
638
+ ## Architecture
639
+
640
+ UI (`src/components/claude/claude-usage-strip.tsx`) → polling hook (`src/hooks/use-claude-usage.ts`) → API route (`src/app/api/claude/usage/route.ts`) → credentials reader (`src/lib/claude/credentials.ts`) + Anthropic fetcher with 30s cache (`src/lib/claude/usage.ts`) → `https://api.anthropic.com/api/oauth/usage`.
641
+
642
+ Polling: hook calls the route on mount and every 60s while the strip is enabled. Server caches the Anthropic response 30s per access-token prefix so rapid re-polls don't hammer Anthropic.
643
+
644
+ ## Key files
645
+
646
+ | Path | Role |
647
+ |---|---|
648
+ | `src/lib/claude/credentials.ts` | Reads `~/.claude/.credentials.json`, extracts `claudeAiOauth`, exposes `isTokenExpired()`. |
649
+ | `src/lib/claude/usage.ts` | Calls Anthropic's `/api/oauth/usage`, 5s timeout, 30s in-memory cache. |
650
+ | `src/app/api/claude/usage/route.ts` | `GET` handler; returns one of `ok` / `unauthenticated` / `expired` / `upstream_error`. |
651
+ | `src/hooks/use-claude-usage.ts` | 60s polling hook, toggled by `enabled` arg. |
652
+ | `src/components/claude/claude-usage-strip.tsx` | Compact 3-bar strip + expanded popover. |
653
+ | `src/app/(desktop)/terminal/page.tsx` | Mounts the strip conditionally in the header. |
654
+ | `src/types/claude.ts` | `RateLimit`, `ExtraUsage`, `Utilization`, `UsageResponse`. |
655
+
656
+ ## Data model
657
+
658
+ No DB tables. All state is transient:
659
+ - Server-side: in-memory `Map<tokenPrefix, { fetchedAt, data }>` in `src/lib/claude/usage.ts` with 30s TTL. Process-local; resets on server restart.
660
+ - Client-side: React state in the hook.
661
+
662
+ ## APIs / contracts
663
+
664
+ ### Internal endpoints
665
+
666
+ - `GET /api/claude/usage` — returns `UsageResponse`:
667
+ - `200 { status: "ok", data: Utilization }` — happy path.
668
+ - `200 { status: "unauthenticated" }` — no credentials file or no `claudeAiOauth`.
669
+ - `200 { status: "expired" }` — access token past `expiresAt`.
670
+ - `200 { status: "upstream_error" }` — Anthropic non-2xx or timeout.
671
+
672
+ Auth: same `withUser`/`getAuthUser` wrapping as every other `/api/*` route.
673
+
674
+ ### External calls
675
+
676
+ - **Anthropic `GET https://api.anthropic.com/api/oauth/usage`** — uses the user's own OAuth access token read from `~/.claude/.credentials.json`. No secret of our own. User-Agent `claude-code/spaces-integration`.
677
+
678
+ ## Configuration & environment
679
+
680
+ - `CLAUDE_CONFIG_DIR` — respected (defaults to `~/.claude`). Same semantics as Claude Code.
681
+ - No env vars, feature flags, or tier gates specific to this feature.
682
+
683
+ ## How to run / test locally
684
+
685
+ ```bash
686
+ npm install
687
+ npm run build
688
+ npm start
689
+ # visit http://localhost:3457/terminal, enter a workspace, add a Claude pane
690
+ ```
691
+
692
+ Manual QA checklist:
693
+
694
+ 1. With a valid OAuth session (logged in via any recent Claude Code run): the strip appears in the header; percents match `/usage` inside Claude Code.
695
+ 2. Hover each bar → tooltip shows the reset timing.
696
+ 3. Click → popover with all five windows and overage block (if applicable).
697
+ 4. Delete the Claude pane from the workspace → strip disappears.
698
+ 5. Set `claudeAiOauth.expiresAt` to a past timestamp in `.credentials.json`, reload → strip shows "sign in via Claude Code".
699
+ 6. Move `.credentials.json` aside temporarily, reload → same sign-in hint.
700
+ 7. Disconnect network → within ~90s the strip silently hides (`upstream_error` → null render).
701
+
702
+ No automated tests for v1.
703
+
704
+ ## Known quirks & decisions
705
+
706
+ - **Passive refresh.** We do not refresh the OAuth access token. Claude Code owns the refresh lifecycle and writes `.credentials.json`; racing with it would corrupt the shared file.
707
+ - **Account-wide data, not per-pane.** The Anthropic endpoint returns account-level rate limits. Rendering once in the header (not per-pane) is intentional.
708
+ - **User-Agent string.** Anthropic classifies callers by UA; we send `claude-code/spaces-integration`. If upstream changes expectations, bump the constant in `src/lib/claude/usage.ts`.
709
+ - **30s cache + 60s poll.** Outer-bound staleness is ~90s; fine for windows that move in hours.
710
+ - **Token-prefix cache key.** First 16 chars of `accessToken`. Collision probability is effectively nil; avoids holding full tokens in the cache structure beyond the single request.
711
+ - **Silent upstream failure.** Errors hide the strip rather than showing a red toast — rate-limit info is nice-to-have, not mission-critical.
712
+ - **Ships direct to `main`.** Per repo convention.
713
+
714
+ ## Open questions / TODOs
715
+
716
+ - [ ] Active OAuth refresh — mirror Claude Code's `/oauth/token` dance to keep the widget live past expiry. Deferred for v1.
717
+ - [ ] Session-cost complement using local JSONL token counts (different data source).
718
+ - [ ] Consider surfacing 7-day-overall alongside the current three for users who care.
719
+
720
+ ## Changelog
721
+
722
+ - 2026-04-22 — Initial implementation. v1 ships direct to `main`.
723
+ ```
724
+
725
+ - [ ] **Step 2: Commit**
726
+
727
+ ```bash
728
+ cd /home/jlongo/development/spaces
729
+ git add docs/features/claude-usage.md
730
+ git commit -m "docs(features): add claude-usage feature doc"
731
+ ```
732
+
733
+ ---
734
+
735
+ ## Self-Review Notes
736
+
737
+ **Spec coverage:** every section of `docs/superpowers/specs/2026-04-22-claude-usage-display-design.md` is implemented:
738
+ - Types → Task 1
739
+ - Credentials reader → Task 1
740
+ - Anthropic fetcher + cache → Task 2
741
+ - API route with four structured statuses → Task 3
742
+ - 60s polling hook → Task 4
743
+ - Component (compact + expanded) → Task 5
744
+ - Conditional header mount → Task 6
745
+ - Feature doc → Task 7
746
+
747
+ **Placeholder scan:** no TBD/TODO outside the feature doc's explicit "Open questions / TODOs" section.
748
+
749
+ **Type consistency:** `Utilization`, `RateLimit`, `ExtraUsage`, `UsageResponse` are defined once in Task 1 and referenced by the same names in Tasks 2 / 3 / 4 / 5 / 7.