@jlongo78/agent-spaces 0.4.0 → 0.5.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/standalone/.claude/settings.local.json +8 -0
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +19 -19
- package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/page.js +2 -2
- package/.next/standalone/.next/server/app/(desktop)/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
- package/.next/standalone/.next/server/app/admin/analytics.rsc +5 -5
- package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/users.html +1 -1
- package/.next/standalone/.next/server/app/admin/users.rsc +5 -5
- package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/analytics.html +1 -1
- package/.next/standalone/.next/server/app/analytics.rsc +5 -5
- package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/admin/analytics/route.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/analytics/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/admin/users/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/users/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/admin/users/route.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/users/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/analytics/overview/route.js +2 -2
- package/.next/standalone/.next/server/app/api/analytics/overview/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/me/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/me/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/totp/setup/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/totp/setup/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/totp/status/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/totp/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/totp/verify/route.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/totp/verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bulk/route.js +2 -2
- package/.next/standalone/.next/server/app/api/bulk/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/chat/route.js +1 -1
- package/.next/standalone/.next/server/app/api/chat/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/config/route.js +1 -1
- package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/events/route.js +2 -2
- package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/folders/route.js +1 -1
- package/.next/standalone/.next/server/app/api/folders/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/discovered/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/discovered/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/handshake/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/handshake/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/health/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/health/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/identity/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/identity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/keys/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/keys/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/keys/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/keys/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/nodes/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/nodes/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/nodes/check/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/nodes/check/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/nodes/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/nodes/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/projects/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/projects/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/proxy/[nodeId]/[...path]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/proxy/[nodeId]/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/search/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/sessions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/terminal/token/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/terminal/token/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/workspaces/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/workspaces/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/panes/[id]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/panes/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/panes/route.js +2 -2
- package/.next/standalone/.next/server/app/api/panes/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/route.js +2 -2
- package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/search/route.js +2 -2
- package/.next/standalone/.next/server/app/api/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js +2 -2
- package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js +2 -2
- package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[id]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/route.js +2 -2
- package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sync/route.js +3 -3
- package/.next/standalone/.next/server/app/api/sync/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tags/route.js +2 -2
- package/.next/standalone/.next/server/app/api/tags/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/tier/route.js +1 -1
- package/.next/standalone/.next/server/app/api/tier/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/workspaces/route.js +2 -2
- package/.next/standalone/.next/server/app/api/workspaces/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login.html +1 -1
- package/.next/standalone/.next/server/app/login.rsc +4 -4
- package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/m/projects.html +1 -1
- package/.next/standalone/.next/server/app/m/projects.rsc +5 -5
- package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/m/sessions.html +1 -1
- package/.next/standalone/.next/server/app/m/sessions.rsc +5 -5
- package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/m/settings.html +1 -1
- package/.next/standalone/.next/server/app/m/settings.rsc +5 -5
- package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/m/terminal.html +1 -1
- package/.next/standalone/.next/server/app/m/terminal.rsc +5 -5
- package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m.html +1 -1
- package/.next/standalone/.next/server/app/m.rsc +5 -5
- package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/network.html +1 -1
- package/.next/standalone/.next/server/app/network.rsc +5 -5
- package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/projects.html +1 -1
- package/.next/standalone/.next/server/app/projects.rsc +5 -5
- package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/sessions.html +1 -1
- package/.next/standalone/.next/server/app/sessions.rsc +5 -5
- package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/settings.html +1 -1
- package/.next/standalone/.next/server/app/settings.rsc +5 -5
- package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/terminal.html +1 -1
- package/.next/standalone/.next/server/app/terminal.rsc +5 -5
- package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/workspaces.html +1 -1
- package/.next/standalone/.next/server/app/workspaces.rsc +5 -5
- package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +5 -5
- package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__086be15a._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0955695e._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fac388d._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__18a58c5f._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__190b05d8._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a211143._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20353b76._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2861e096._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a7a798c._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2b6758fc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2e9d1d5a._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__31f028ec._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__34c34116._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__3aa57139._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__3ce30e4e._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__41ae8be6._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__41e589ee._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__43112c34._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__464db440._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__466c7e18._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__47a63195._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__4ad64489._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__5bbc73ff._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__60689e2b._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__67c4abf3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__6b94cc47._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c6cfe82._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__776b2fd5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__7901e2ab._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__83b9bcf3._.js +11 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__89124c96._.js +243 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__8c2eee30._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__8ffcf827._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__95b7f18e._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e343d64._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a2ee9884._.js +13 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a651ede9._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a6ce192e._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__b4b692df._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__b4edb4d6._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__b71497ab._.js +243 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__bc97ddc7._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__bef2ed87._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c525457e._.js +19 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c546cf71._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__ccc27199._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__ce5edd98._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__d877df12._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__dd2e81be._.js +11 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__de96c005._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__df6bc9e9._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__e2b78951._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__e742ef33._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__63c35e0f._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1f12caba._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_3b54193d._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_43e7e611._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_5ac43c5d._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_cd50a174._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_terminal_page_tsx_de5e8d85._.js +1 -1
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__32a0045c._.js +1 -1
- package/.next/standalone/.next/server/edge/chunks/_d73df637._.js +3 -0
- package/.next/standalone/.next/server/edge/chunks/turbopack-node_modules_next_dist_esm_build_templates_edge-wrapper_a4434a38.js +6 -0
- package/.next/standalone/.next/server/middleware-manifest.json +7 -7
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +2 -2
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{31f45c67350373f2.js → 10c6424526b53431.js} +2 -2
- package/.next/standalone/.next/static/chunks/{8cc07e8d950d6962.js → 27649ec994a696fb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3c4ee171d96760e8.js → 302ce212c690bec4.js} +2 -2
- package/.next/standalone/.next/static/chunks/51dacec57c9714c0.js +1 -0
- package/.next/standalone/.next/static/chunks/{f2b58d718b34646d.js → 53782d1e41fd7f82.js} +1 -1
- package/.next/standalone/.next/static/chunks/{f789a1d0736e1154.js → 58d78765e5140dcb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{7c1e6d7f1d3b4173.js → cb442c50eecb758d.js} +2 -2
- package/.next/standalone/.next/static/chunks/ff5fac1bd7b518dd.css +3 -0
- package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
- package/.next/standalone/node_modules/@img/{sharp-linux-x64 → sharp-win32-x64}/package.json +39 -46
- package/.next/standalone/package.json +89 -91
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/tsconfig.json +34 -34
- package/LICENSE +661 -661
- package/README.md +131 -131
- package/bin/fix-standalone-externals.js +79 -79
- package/bin/lib/auto-setup.js +101 -101
- package/bin/mdns-service.js +171 -171
- package/bin/postinstall.js +35 -35
- package/bin/setup-admin.js +189 -189
- package/bin/spaces-dev.js +208 -173
- package/bin/spaces-install.js +425 -0
- package/bin/spaces-setup.js +242 -242
- package/bin/spaces.js +466 -318
- package/bin/terminal-server.js +1117 -1051
- package/package.json +89 -91
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__025cd038._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__042ba2bc._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07cc153d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08e411dd._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0add852f._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0c113ed0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cf032ab._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__11293532._.js +0 -13
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1194f2c1._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19c2d094._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19c3ad21._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ebc634e._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__24197539._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2891c969._.js +0 -11
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2c6e6625._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__2fe2b40e._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__318f12c6._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__32df12e4._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__34e7cb21._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__49c92d87._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__52bde30c._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__53090a81._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__57193cf5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c33078d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__5f8c694a._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__630b9a6a._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__727d05f1._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__75a774f0._.js +0 -233
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__7f0bc701._.js +0 -233
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__8915603e._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__8afe4d5e._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__9d15de27._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a1fbc199._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a1fe6070._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a3f604d6._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__a5504205._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__abf53d11._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__b78eeead._.js +0 -11
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c1b8f8f6._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c3c74ca4._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c79824d9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c9db5d8a._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__cbd9cb15._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__ccb4e920._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__d15515e3._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__d490583e._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__d9c106a9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__de2c3bf8._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__dfbf7bdd._.js +0 -19
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__e1e26f47._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__ee9346bf._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__fea012d6._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff1b0769._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__eac7aeff._.js +0 -3
- package/.next/standalone/.next/server/edge/chunks/node_modules_next_dist_esm_build_templates_edge-wrapper_78fa9d6a.js +0 -3
- package/.next/standalone/.next/server/edge/chunks/turbopack-node_modules_next_dist_esm_build_templates_edge-wrapper_a5230bba.js +0 -6
- package/.next/standalone/.next/static/chunks/780381483091d8fb.js +0 -1
- package/.next/standalone/.next/static/chunks/806334ea0f6ca92a.css +0 -3
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +0 -46
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +0 -221
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +0 -1
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +0 -42
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +0 -46
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +0 -221
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +0 -1
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +0 -42
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +0 -30
- package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
- package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
- package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +0 -46
- /package/.next/standalone/.next/static/{k4gRsS979E-cbl1AWcHhx → MjMvcPAGPqPwAzs1S2njU}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{k4gRsS979E-cbl1AWcHhx → MjMvcPAGPqPwAzs1S2njU}/_clientMiddlewareManifest.json +0 -0
- /package/.next/standalone/.next/static/{k4gRsS979E-cbl1AWcHhx → MjMvcPAGPqPwAzs1S2njU}/_ssgManifest.js +0 -0
- /package/.next/standalone/node_modules/@img/{sharp-libvips-linux-x64 → sharp-win32-x64}/versions.json +0 -0
package/README.md
CHANGED
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="public/spaces_logo.png" alt="Spaces" width="420" />
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<h3 align="center">The workspace manager for AI coding agents</h3>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
Run Claude Code, Codex CLI, Gemini CLI, Aider, or any agent side-by-side<br/>
|
|
9
|
-
in a browser-based terminal grid. Totally free. Totally open source.
|
|
10
|
-
</p>
|
|
11
|
-
|
|
12
|
-
<p align="center">
|
|
13
|
-
<a href="#quick-start">Quick Start</a> ·
|
|
14
|
-
<a href="#features">Features</a> ·
|
|
15
|
-
<a href="docs/getting-started.md">Full Docs</a>
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
|
-
<p align="center">
|
|
19
|
-
<a href="https://www.npmjs.com/package/@jlongo78/agent-spaces"><img src="https://img.shields.io/npm/v/@jlongo78/agent-spaces?style=flat-square&color=cb3837" alt="npm" /></a>
|
|
20
|
-
<a href="https://github.com/jlongo78/spaces/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/jlongo78/spaces/ci.yml?style=flat-square&label=CI" alt="CI" /></a>
|
|
21
|
-
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT License" /></a>
|
|
22
|
-
<img src="https://img.shields.io/badge/node-%3E%3D20.9-brightgreen?style=flat-square" alt="Node 20.9+" />
|
|
23
|
-
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux%20%7C%20ARM64-lightgrey?style=flat-square" alt="Platforms" />
|
|
24
|
-
</p>
|
|
25
|
-
|
|
26
|
-
<p align="center">
|
|
27
|
-
<img src="public/demo.gif" alt="Spaces demo" width="800" />
|
|
28
|
-
</p>
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## What is Spaces?
|
|
33
|
-
|
|
34
|
-
Most AI coding agents are powerful but isolated — one terminal, one session, one agent at a time. **Spaces** changes that.
|
|
35
|
-
|
|
36
|
-
Open your browser and get a full terminal grid where every pane is a real PTY. Spin up Claude in one pane, Codex in another, a plain shell in a third. Group them into named workspaces. Search across every session you've ever had. See your usage stats at a glance.
|
|
37
|
-
|
|
38
|
-
Everything runs locally. Your data never leaves your machine.
|
|
39
|
-
|
|
40
|
-
## Quick Start
|
|
41
|
-
|
|
42
|
-
### Install from npm (recommended)
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
npm install -g @jlongo78/agent-spaces
|
|
46
|
-
spaces
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Or build from source
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
git clone https://github.com/jlongo78/spaces.git
|
|
53
|
-
cd spaces
|
|
54
|
-
npm install
|
|
55
|
-
npm run build
|
|
56
|
-
npm start
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Open [http://localhost:3457](http://localhost:3457) and start adding panes.
|
|
60
|
-
|
|
61
|
-
## Features
|
|
62
|
-
|
|
63
|
-
### Terminal Multiplexer
|
|
64
|
-
Split your browser into a grid of terminal panes. Each one runs a real PTY streamed over WebSocket to xterm.js — not a toy emulator.
|
|
65
|
-
|
|
66
|
-
### Agent-Agnostic
|
|
67
|
-
First-class support for **Claude Code**, **Codex CLI**, **Gemini CLI**, **Aider**, any custom command, and plain shell. Pick your agent per-pane from a dropdown.
|
|
68
|
-
|
|
69
|
-
### Workspaces
|
|
70
|
-
Group panes into named, color-coded spaces. Working on the frontend and the API at the same time? Give each its own workspace and switch instantly.
|
|
71
|
-
|
|
72
|
-
### Session Browser
|
|
73
|
-
Every agent session (Claude, Codex, Gemini, Aider) is indexed automatically. Browse, search, and filter with full-text search powered by SQLite FTS5. Jump back into any conversation.
|
|
74
|
-
|
|
75
|
-
### Dashboard & Analytics
|
|
76
|
-
Session counts, token usage breakdown by model, activity heatmap, and cost estimates — all computed locally from your `~/.claude/` data.
|
|
77
|
-
|
|
78
|
-
### Everything Local
|
|
79
|
-
Zero cloud dependencies. No accounts. No telemetry by default. All data lives in `~/.claude/` (read-only) and `~/.spaces/` (auto-created). Fully offline-capable.
|
|
80
|
-
|
|
81
|
-
## Advanced Tiers
|
|
82
|
-
|
|
83
|
-
The Community edition above is fully open source (MIT) and free forever. For teams and organizations, Spaces also supports multi-user auth, admin panels, federated node networks, and remote workspaces through optional paid tiers.
|
|
84
|
-
|
|
85
|
-
| | Community | Server | Team | Federation |
|
|
86
|
-
|---|:---------:|:------:|:----:|:----------:|
|
|
87
|
-
| Multi-pane terminals | Yes | Yes | Yes | Yes |
|
|
88
|
-
| Session browser & search | Yes | Yes | Yes | Yes |
|
|
89
|
-
| Dashboard & analytics | Yes | Yes | Yes | Yes |
|
|
90
|
-
| Browser access | Yes | Yes | Yes | Yes |
|
|
91
|
-
| Login & TOTP auth | - | Yes | Yes | Yes |
|
|
92
|
-
| Multi-user accounts | - | - | Yes | Yes |
|
|
93
|
-
| Admin panel | - | - | Yes | Yes |
|
|
94
|
-
| Federated node network | - | - | - | Yes |
|
|
95
|
-
| Remote workspaces | - | - | - | Yes |
|
|
96
|
-
| mDNS auto-discovery | - | - | - | Yes |
|
|
97
|
-
|
|
98
|
-
See [docs/tiers.md](docs/tiers.md) for details.
|
|
99
|
-
|
|
100
|
-
## Tech Stack
|
|
101
|
-
|
|
102
|
-
| Layer | Technology |
|
|
103
|
-
|-------|------------|
|
|
104
|
-
| Framework | Next.js 16 (App Router) |
|
|
105
|
-
| UI | React 19, Tailwind CSS, Lucide icons |
|
|
106
|
-
| Database | SQLite via better-sqlite3, FTS5 full-text search |
|
|
107
|
-
| Terminal | xterm.js + node-pty over WebSocket |
|
|
108
|
-
| Runtime | Node.js (CLI) |
|
|
109
|
-
|
|
110
|
-
## Configuration
|
|
111
|
-
|
|
112
|
-
| Variable | Default | Description |
|
|
113
|
-
|----------|---------|-------------|
|
|
114
|
-
| `SPACES_PORT` | `3457` | Web UI port |
|
|
115
|
-
| `SPACES_WS_PORT` | `3458` | Terminal WebSocket port |
|
|
116
|
-
| `NEXT_PUBLIC_TIER` | `community` | Product tier |
|
|
117
|
-
|
|
118
|
-
Data lives in:
|
|
119
|
-
- **`~/.claude/`** — Claude Code sessions (read-only)
|
|
120
|
-
- **`~/.codex/`** — Codex CLI sessions (read-only)
|
|
121
|
-
- **`~/.gemini/`** — Gemini CLI sessions (read-only)
|
|
122
|
-
- **`.aider.chat.history.md`** — Aider sessions in each project directory (read-only)
|
|
123
|
-
- **`~/.spaces/`** — Spaces database and config (auto-created)
|
|
124
|
-
|
|
125
|
-
## Contributing
|
|
126
|
-
|
|
127
|
-
Contributions are welcome. Please open an issue first to discuss what you'd like to change.
|
|
128
|
-
|
|
129
|
-
## License
|
|
130
|
-
|
|
131
|
-
[MIT](LICENSE)
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="public/spaces_logo.png" alt="Spaces" width="420" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h3 align="center">The workspace manager for AI coding agents</h3>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Run Claude Code, Codex CLI, Gemini CLI, Aider, or any agent side-by-side<br/>
|
|
9
|
+
in a browser-based terminal grid. Totally free. Totally open source.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="#quick-start">Quick Start</a> ·
|
|
14
|
+
<a href="#features">Features</a> ·
|
|
15
|
+
<a href="docs/getting-started.md">Full Docs</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://www.npmjs.com/package/@jlongo78/agent-spaces"><img src="https://img.shields.io/npm/v/@jlongo78/agent-spaces?style=flat-square&color=cb3837" alt="npm" /></a>
|
|
20
|
+
<a href="https://github.com/jlongo78/spaces/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/jlongo78/spaces/ci.yml?style=flat-square&label=CI" alt="CI" /></a>
|
|
21
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT License" /></a>
|
|
22
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20.9-brightgreen?style=flat-square" alt="Node 20.9+" />
|
|
23
|
+
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux%20%7C%20ARM64-lightgrey?style=flat-square" alt="Platforms" />
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
<p align="center">
|
|
27
|
+
<img src="public/demo.gif" alt="Spaces demo" width="800" />
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## What is Spaces?
|
|
33
|
+
|
|
34
|
+
Most AI coding agents are powerful but isolated — one terminal, one session, one agent at a time. **Spaces** changes that.
|
|
35
|
+
|
|
36
|
+
Open your browser and get a full terminal grid where every pane is a real PTY. Spin up Claude in one pane, Codex in another, a plain shell in a third. Group them into named workspaces. Search across every session you've ever had. See your usage stats at a glance.
|
|
37
|
+
|
|
38
|
+
Everything runs locally. Your data never leaves your machine.
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### Install from npm (recommended)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install -g @jlongo78/agent-spaces
|
|
46
|
+
spaces
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Or build from source
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git clone https://github.com/jlongo78/spaces.git
|
|
53
|
+
cd spaces
|
|
54
|
+
npm install
|
|
55
|
+
npm run build
|
|
56
|
+
npm start
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Open [http://localhost:3457](http://localhost:3457) and start adding panes.
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
### Terminal Multiplexer
|
|
64
|
+
Split your browser into a grid of terminal panes. Each one runs a real PTY streamed over WebSocket to xterm.js — not a toy emulator.
|
|
65
|
+
|
|
66
|
+
### Agent-Agnostic
|
|
67
|
+
First-class support for **Claude Code**, **Codex CLI**, **Gemini CLI**, **Aider**, any custom command, and plain shell. Pick your agent per-pane from a dropdown.
|
|
68
|
+
|
|
69
|
+
### Workspaces
|
|
70
|
+
Group panes into named, color-coded spaces. Working on the frontend and the API at the same time? Give each its own workspace and switch instantly.
|
|
71
|
+
|
|
72
|
+
### Session Browser
|
|
73
|
+
Every agent session (Claude, Codex, Gemini, Aider) is indexed automatically. Browse, search, and filter with full-text search powered by SQLite FTS5. Jump back into any conversation.
|
|
74
|
+
|
|
75
|
+
### Dashboard & Analytics
|
|
76
|
+
Session counts, token usage breakdown by model, activity heatmap, and cost estimates — all computed locally from your `~/.claude/` data.
|
|
77
|
+
|
|
78
|
+
### Everything Local
|
|
79
|
+
Zero cloud dependencies. No accounts. No telemetry by default. All data lives in `~/.claude/` (read-only) and `~/.spaces/` (auto-created). Fully offline-capable.
|
|
80
|
+
|
|
81
|
+
## Advanced Tiers
|
|
82
|
+
|
|
83
|
+
The Community edition above is fully open source (MIT) and free forever. For teams and organizations, Spaces also supports multi-user auth, admin panels, federated node networks, and remote workspaces through optional paid tiers.
|
|
84
|
+
|
|
85
|
+
| | Community | Server | Team | Federation |
|
|
86
|
+
|---|:---------:|:------:|:----:|:----------:|
|
|
87
|
+
| Multi-pane terminals | Yes | Yes | Yes | Yes |
|
|
88
|
+
| Session browser & search | Yes | Yes | Yes | Yes |
|
|
89
|
+
| Dashboard & analytics | Yes | Yes | Yes | Yes |
|
|
90
|
+
| Browser access | Yes | Yes | Yes | Yes |
|
|
91
|
+
| Login & TOTP auth | - | Yes | Yes | Yes |
|
|
92
|
+
| Multi-user accounts | - | - | Yes | Yes |
|
|
93
|
+
| Admin panel | - | - | Yes | Yes |
|
|
94
|
+
| Federated node network | - | - | - | Yes |
|
|
95
|
+
| Remote workspaces | - | - | - | Yes |
|
|
96
|
+
| mDNS auto-discovery | - | - | - | Yes |
|
|
97
|
+
|
|
98
|
+
See [docs/tiers.md](docs/tiers.md) for details.
|
|
99
|
+
|
|
100
|
+
## Tech Stack
|
|
101
|
+
|
|
102
|
+
| Layer | Technology |
|
|
103
|
+
|-------|------------|
|
|
104
|
+
| Framework | Next.js 16 (App Router) |
|
|
105
|
+
| UI | React 19, Tailwind CSS, Lucide icons |
|
|
106
|
+
| Database | SQLite via better-sqlite3, FTS5 full-text search |
|
|
107
|
+
| Terminal | xterm.js + node-pty over WebSocket |
|
|
108
|
+
| Runtime | Node.js (CLI) |
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
| Variable | Default | Description |
|
|
113
|
+
|----------|---------|-------------|
|
|
114
|
+
| `SPACES_PORT` | `3457` | Web UI port |
|
|
115
|
+
| `SPACES_WS_PORT` | `3458` | Terminal WebSocket port |
|
|
116
|
+
| `NEXT_PUBLIC_TIER` | `community` | Product tier |
|
|
117
|
+
|
|
118
|
+
Data lives in:
|
|
119
|
+
- **`~/.claude/`** — Claude Code sessions (read-only)
|
|
120
|
+
- **`~/.codex/`** — Codex CLI sessions (read-only)
|
|
121
|
+
- **`~/.gemini/`** — Gemini CLI sessions (read-only)
|
|
122
|
+
- **`.aider.chat.history.md`** — Aider sessions in each project directory (read-only)
|
|
123
|
+
- **`~/.spaces/`** — Spaces database and config (auto-created)
|
|
124
|
+
|
|
125
|
+
## Contributing
|
|
126
|
+
|
|
127
|
+
Contributions are welcome. Please open an issue first to discuss what you'd like to change.
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
[MIT](LICENSE)
|
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Turbopack mangles serverExternalPackages names with a hash suffix
|
|
4
|
-
// (e.g. "better-sqlite3-90e2652d1716b047"). This script scans the
|
|
5
|
-
// standalone build output, finds all mangled require() calls, and
|
|
6
|
-
// creates proxy modules so the standalone server can resolve them.
|
|
7
|
-
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
|
|
11
|
-
const chunksDir = path.join(__dirname, '..', '.next', 'standalone', '.next', 'server', 'chunks');
|
|
12
|
-
const standaloneModules = path.join(__dirname, '..', '.next', 'standalone', 'node_modules');
|
|
13
|
-
|
|
14
|
-
if (!fs.existsSync(chunksDir)) {
|
|
15
|
-
console.log('[fix-externals] No standalone chunks found, skipping.');
|
|
16
|
-
process.exit(0);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Scan all JS chunk files for mangled external requires
|
|
20
|
-
const re = /require\("([a-z@][a-z0-9@/_.-]*)-([0-9a-f]{16})"\)/g;
|
|
21
|
-
const aliases = new Map(); // mangled name -> real package name
|
|
22
|
-
|
|
23
|
-
const files = fs.readdirSync(chunksDir).filter(f => f.endsWith('.js'));
|
|
24
|
-
for (const file of files) {
|
|
25
|
-
const content = fs.readFileSync(path.join(chunksDir, file), 'utf-8');
|
|
26
|
-
let match;
|
|
27
|
-
while ((match = re.exec(content)) !== null) {
|
|
28
|
-
const mangledName = `${match[1]}-${match[2]}`;
|
|
29
|
-
const realName = match[1];
|
|
30
|
-
aliases.set(mangledName, realName);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (aliases.size === 0) {
|
|
35
|
-
console.log('[fix-externals] No mangled externals found.');
|
|
36
|
-
process.exit(0);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
for (const [alias, real] of aliases) {
|
|
40
|
-
const aliasDir = path.join(standaloneModules, alias);
|
|
41
|
-
if (fs.existsSync(aliasDir)) continue;
|
|
42
|
-
|
|
43
|
-
fs.mkdirSync(aliasDir, { recursive: true });
|
|
44
|
-
fs.writeFileSync(
|
|
45
|
-
path.join(aliasDir, 'index.js'),
|
|
46
|
-
`module.exports = require(${JSON.stringify(real)});\n`
|
|
47
|
-
);
|
|
48
|
-
fs.writeFileSync(
|
|
49
|
-
path.join(aliasDir, 'package.json'),
|
|
50
|
-
JSON.stringify({ name: alias, version: '1.0.0', main: 'index.js' }) + '\n'
|
|
51
|
-
);
|
|
52
|
-
console.log(`[fix-externals] Created alias: ${alias} -> ${real}`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Remove native modules from the standalone bundle.
|
|
56
|
-
// Next.js standalone mode copies all traced dependencies into
|
|
57
|
-
// .next/standalone/node_modules/, including pre-compiled native addons.
|
|
58
|
-
// These binaries are built for the CI Node version and will fail on
|
|
59
|
-
// machines running a different Node version (NODE_MODULE_VERSION mismatch).
|
|
60
|
-
// Removing them forces resolution to the parent node_modules/ where
|
|
61
|
-
// the postinstall `npm rebuild` compiles them for the user's Node version.
|
|
62
|
-
const nativeModules = ['better-sqlite3', 'node-pty'];
|
|
63
|
-
for (const mod of nativeModules) {
|
|
64
|
-
const modDir = path.join(standaloneModules, mod);
|
|
65
|
-
if (fs.existsSync(modDir)) {
|
|
66
|
-
fs.rmSync(modDir, { recursive: true, force: true });
|
|
67
|
-
console.log(`[fix-externals] Removed native module from standalone: ${mod}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Also remove transitive native dependencies that Next.js may have copied
|
|
72
|
-
const nativeTransitive = ['bindings', 'file-uri-to-path', 'detect-libc'];
|
|
73
|
-
for (const mod of nativeTransitive) {
|
|
74
|
-
const modDir = path.join(standaloneModules, mod);
|
|
75
|
-
if (fs.existsSync(modDir)) {
|
|
76
|
-
fs.rmSync(modDir, { recursive: true, force: true });
|
|
77
|
-
console.log(`[fix-externals] Removed transitive native dep from standalone: ${mod}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Turbopack mangles serverExternalPackages names with a hash suffix
|
|
4
|
+
// (e.g. "better-sqlite3-90e2652d1716b047"). This script scans the
|
|
5
|
+
// standalone build output, finds all mangled require() calls, and
|
|
6
|
+
// creates proxy modules so the standalone server can resolve them.
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const chunksDir = path.join(__dirname, '..', '.next', 'standalone', '.next', 'server', 'chunks');
|
|
12
|
+
const standaloneModules = path.join(__dirname, '..', '.next', 'standalone', 'node_modules');
|
|
13
|
+
|
|
14
|
+
if (!fs.existsSync(chunksDir)) {
|
|
15
|
+
console.log('[fix-externals] No standalone chunks found, skipping.');
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Scan all JS chunk files for mangled external requires
|
|
20
|
+
const re = /require\("([a-z@][a-z0-9@/_.-]*)-([0-9a-f]{16})"\)/g;
|
|
21
|
+
const aliases = new Map(); // mangled name -> real package name
|
|
22
|
+
|
|
23
|
+
const files = fs.readdirSync(chunksDir).filter(f => f.endsWith('.js'));
|
|
24
|
+
for (const file of files) {
|
|
25
|
+
const content = fs.readFileSync(path.join(chunksDir, file), 'utf-8');
|
|
26
|
+
let match;
|
|
27
|
+
while ((match = re.exec(content)) !== null) {
|
|
28
|
+
const mangledName = `${match[1]}-${match[2]}`;
|
|
29
|
+
const realName = match[1];
|
|
30
|
+
aliases.set(mangledName, realName);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (aliases.size === 0) {
|
|
35
|
+
console.log('[fix-externals] No mangled externals found.');
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const [alias, real] of aliases) {
|
|
40
|
+
const aliasDir = path.join(standaloneModules, alias);
|
|
41
|
+
if (fs.existsSync(aliasDir)) continue;
|
|
42
|
+
|
|
43
|
+
fs.mkdirSync(aliasDir, { recursive: true });
|
|
44
|
+
fs.writeFileSync(
|
|
45
|
+
path.join(aliasDir, 'index.js'),
|
|
46
|
+
`module.exports = require(${JSON.stringify(real)});\n`
|
|
47
|
+
);
|
|
48
|
+
fs.writeFileSync(
|
|
49
|
+
path.join(aliasDir, 'package.json'),
|
|
50
|
+
JSON.stringify({ name: alias, version: '1.0.0', main: 'index.js' }) + '\n'
|
|
51
|
+
);
|
|
52
|
+
console.log(`[fix-externals] Created alias: ${alias} -> ${real}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Remove native modules from the standalone bundle.
|
|
56
|
+
// Next.js standalone mode copies all traced dependencies into
|
|
57
|
+
// .next/standalone/node_modules/, including pre-compiled native addons.
|
|
58
|
+
// These binaries are built for the CI Node version and will fail on
|
|
59
|
+
// machines running a different Node version (NODE_MODULE_VERSION mismatch).
|
|
60
|
+
// Removing them forces resolution to the parent node_modules/ where
|
|
61
|
+
// the postinstall `npm rebuild` compiles them for the user's Node version.
|
|
62
|
+
const nativeModules = ['better-sqlite3', 'node-pty'];
|
|
63
|
+
for (const mod of nativeModules) {
|
|
64
|
+
const modDir = path.join(standaloneModules, mod);
|
|
65
|
+
if (fs.existsSync(modDir)) {
|
|
66
|
+
fs.rmSync(modDir, { recursive: true, force: true });
|
|
67
|
+
console.log(`[fix-externals] Removed native module from standalone: ${mod}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Also remove transitive native dependencies that Next.js may have copied
|
|
72
|
+
const nativeTransitive = ['bindings', 'file-uri-to-path', 'detect-libc'];
|
|
73
|
+
for (const mod of nativeTransitive) {
|
|
74
|
+
const modDir = path.join(standaloneModules, mod);
|
|
75
|
+
if (fs.existsSync(modDir)) {
|
|
76
|
+
fs.rmSync(modDir, { recursive: true, force: true });
|
|
77
|
+
console.log(`[fix-externals] Removed transitive native dep from standalone: ${mod}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
package/bin/lib/auto-setup.js
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
// Non-interactive first-time setup for Spaces federation edition.
|
|
2
|
-
// Called automatically when @spaces/pro is detected but admin.db or session_secret are missing.
|
|
3
|
-
// For interactive customization, use: spaces --setup
|
|
4
|
-
|
|
5
|
-
const Database = require('better-sqlite3');
|
|
6
|
-
const crypto = require('crypto');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const os = require('os');
|
|
10
|
-
|
|
11
|
-
function hashPassword(password) {
|
|
12
|
-
const salt = crypto.randomBytes(16).toString('hex');
|
|
13
|
-
const hash = crypto.scryptSync(password, salt, 64).toString('hex');
|
|
14
|
-
return `${salt}:${hash}`;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function generatePassword() {
|
|
18
|
-
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
|
|
19
|
-
let password = '';
|
|
20
|
-
const bytes = crypto.randomBytes(16);
|
|
21
|
-
for (let i = 0; i < 16; i++) {
|
|
22
|
-
password += chars[bytes[i] % chars.length];
|
|
23
|
-
}
|
|
24
|
-
return password;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function autoSetup({ SPACES_DIR, SESSION_SECRET_PATH, ADMIN_DB_PATH, CONFIG_PATH, tier, port, basePath }) {
|
|
28
|
-
// Ensure ~/.spaces directory
|
|
29
|
-
if (!fs.existsSync(SPACES_DIR)) {
|
|
30
|
-
fs.mkdirSync(SPACES_DIR, { recursive: true });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Generate session secret
|
|
34
|
-
let sessionSecret;
|
|
35
|
-
if (fs.existsSync(SESSION_SECRET_PATH)) {
|
|
36
|
-
sessionSecret = fs.readFileSync(SESSION_SECRET_PATH, 'utf-8').trim();
|
|
37
|
-
}
|
|
38
|
-
if (!sessionSecret) {
|
|
39
|
-
sessionSecret = crypto.randomBytes(32).toString('hex');
|
|
40
|
-
fs.writeFileSync(SESSION_SECRET_PATH, sessionSecret, { mode: 0o600 });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Create admin DB and user
|
|
44
|
-
let generatedPassword = null;
|
|
45
|
-
if (!fs.existsSync(ADMIN_DB_PATH)) {
|
|
46
|
-
const db = new Database(ADMIN_DB_PATH);
|
|
47
|
-
db.pragma('journal_mode = WAL');
|
|
48
|
-
db.pragma('synchronous = NORMAL');
|
|
49
|
-
db.pragma('foreign_keys = ON');
|
|
50
|
-
|
|
51
|
-
db.exec(`
|
|
52
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
53
|
-
id TEXT PRIMARY KEY,
|
|
54
|
-
username TEXT NOT NULL UNIQUE,
|
|
55
|
-
password_hash TEXT NOT NULL,
|
|
56
|
-
display_name TEXT NOT NULL DEFAULT '',
|
|
57
|
-
shell_user TEXT NOT NULL,
|
|
58
|
-
role TEXT NOT NULL DEFAULT 'user',
|
|
59
|
-
totp_secret TEXT,
|
|
60
|
-
totp_enabled INTEGER DEFAULT 0,
|
|
61
|
-
created TEXT DEFAULT (datetime('now'))
|
|
62
|
-
);
|
|
63
|
-
`);
|
|
64
|
-
|
|
65
|
-
generatedPassword = generatePassword();
|
|
66
|
-
const shellUser = os.userInfo().username;
|
|
67
|
-
const id = crypto.randomUUID();
|
|
68
|
-
const passwordHash = hashPassword(generatedPassword);
|
|
69
|
-
|
|
70
|
-
db.prepare(`
|
|
71
|
-
INSERT INTO users (id, username, password_hash, display_name, shell_user, role)
|
|
72
|
-
VALUES (?, ?, ?, ?, ?, 'admin')
|
|
73
|
-
`).run(id, 'admin', passwordHash, 'Admin', shellUser);
|
|
74
|
-
|
|
75
|
-
db.close();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Save server.json if it doesn't exist
|
|
79
|
-
if (!fs.existsSync(CONFIG_PATH)) {
|
|
80
|
-
const config = { tier, port: port || 3457, basePath: basePath || '' };
|
|
81
|
-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Print credentials box
|
|
85
|
-
if (generatedPassword) {
|
|
86
|
-
console.log('');
|
|
87
|
-
console.log(' ┌──────────────────────────────────────────┐');
|
|
88
|
-
console.log(' │ First-time setup complete │');
|
|
89
|
-
console.log(' │ │');
|
|
90
|
-
console.log(' │ Username: admin │');
|
|
91
|
-
console.log(` │ Password: ${generatedPassword} │`);
|
|
92
|
-
console.log(' │ │');
|
|
93
|
-
console.log(' │ Run `spaces --setup` to customize. │');
|
|
94
|
-
console.log(' └──────────────────────────────────────────┘');
|
|
95
|
-
console.log('');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return { sessionSecret, generatedPassword };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
module.exports = { autoSetup, hashPassword, generatePassword };
|
|
1
|
+
// Non-interactive first-time setup for Spaces federation edition.
|
|
2
|
+
// Called automatically when @spaces/pro is detected but admin.db or session_secret are missing.
|
|
3
|
+
// For interactive customization, use: spaces --setup
|
|
4
|
+
|
|
5
|
+
const Database = require('better-sqlite3');
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
|
|
11
|
+
function hashPassword(password) {
|
|
12
|
+
const salt = crypto.randomBytes(16).toString('hex');
|
|
13
|
+
const hash = crypto.scryptSync(password, salt, 64).toString('hex');
|
|
14
|
+
return `${salt}:${hash}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function generatePassword() {
|
|
18
|
+
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
|
|
19
|
+
let password = '';
|
|
20
|
+
const bytes = crypto.randomBytes(16);
|
|
21
|
+
for (let i = 0; i < 16; i++) {
|
|
22
|
+
password += chars[bytes[i] % chars.length];
|
|
23
|
+
}
|
|
24
|
+
return password;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function autoSetup({ SPACES_DIR, SESSION_SECRET_PATH, ADMIN_DB_PATH, CONFIG_PATH, tier, port, basePath }) {
|
|
28
|
+
// Ensure ~/.spaces directory
|
|
29
|
+
if (!fs.existsSync(SPACES_DIR)) {
|
|
30
|
+
fs.mkdirSync(SPACES_DIR, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Generate session secret
|
|
34
|
+
let sessionSecret;
|
|
35
|
+
if (fs.existsSync(SESSION_SECRET_PATH)) {
|
|
36
|
+
sessionSecret = fs.readFileSync(SESSION_SECRET_PATH, 'utf-8').trim();
|
|
37
|
+
}
|
|
38
|
+
if (!sessionSecret) {
|
|
39
|
+
sessionSecret = crypto.randomBytes(32).toString('hex');
|
|
40
|
+
fs.writeFileSync(SESSION_SECRET_PATH, sessionSecret, { mode: 0o600 });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Create admin DB and user
|
|
44
|
+
let generatedPassword = null;
|
|
45
|
+
if (!fs.existsSync(ADMIN_DB_PATH)) {
|
|
46
|
+
const db = new Database(ADMIN_DB_PATH);
|
|
47
|
+
db.pragma('journal_mode = WAL');
|
|
48
|
+
db.pragma('synchronous = NORMAL');
|
|
49
|
+
db.pragma('foreign_keys = ON');
|
|
50
|
+
|
|
51
|
+
db.exec(`
|
|
52
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
username TEXT NOT NULL UNIQUE,
|
|
55
|
+
password_hash TEXT NOT NULL,
|
|
56
|
+
display_name TEXT NOT NULL DEFAULT '',
|
|
57
|
+
shell_user TEXT NOT NULL,
|
|
58
|
+
role TEXT NOT NULL DEFAULT 'user',
|
|
59
|
+
totp_secret TEXT,
|
|
60
|
+
totp_enabled INTEGER DEFAULT 0,
|
|
61
|
+
created TEXT DEFAULT (datetime('now'))
|
|
62
|
+
);
|
|
63
|
+
`);
|
|
64
|
+
|
|
65
|
+
generatedPassword = generatePassword();
|
|
66
|
+
const shellUser = os.userInfo().username;
|
|
67
|
+
const id = crypto.randomUUID();
|
|
68
|
+
const passwordHash = hashPassword(generatedPassword);
|
|
69
|
+
|
|
70
|
+
db.prepare(`
|
|
71
|
+
INSERT INTO users (id, username, password_hash, display_name, shell_user, role)
|
|
72
|
+
VALUES (?, ?, ?, ?, ?, 'admin')
|
|
73
|
+
`).run(id, 'admin', passwordHash, 'Admin', shellUser);
|
|
74
|
+
|
|
75
|
+
db.close();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Save server.json if it doesn't exist
|
|
79
|
+
if (!fs.existsSync(CONFIG_PATH)) {
|
|
80
|
+
const config = { tier, port: port || 3457, basePath: basePath || '' };
|
|
81
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Print credentials box
|
|
85
|
+
if (generatedPassword) {
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log(' ┌──────────────────────────────────────────┐');
|
|
88
|
+
console.log(' │ First-time setup complete │');
|
|
89
|
+
console.log(' │ │');
|
|
90
|
+
console.log(' │ Username: admin │');
|
|
91
|
+
console.log(` │ Password: ${generatedPassword} │`);
|
|
92
|
+
console.log(' │ │');
|
|
93
|
+
console.log(' │ Run `spaces --setup` to customize. │');
|
|
94
|
+
console.log(' └──────────────────────────────────────────┘');
|
|
95
|
+
console.log('');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return { sessionSecret, generatedPassword };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { autoSetup, hashPassword, generatePassword };
|