clawpad 0.3.1 → 0.3.3

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 (170) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +9 -9
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/react-loadable-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  8. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +4 -4
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  19. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  22. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/api/ai/write/route_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/api/changes/[id]/route_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/api/changes/record/route_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/api/changes/revert/route_client-reference-manifest.js +1 -1
  28. package/.next/standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/api/changes/run/route_client-reference-manifest.js +1 -1
  30. package/.next/standalone/.next/server/app/api/chat/abort/route_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/api/chat/route_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/api/files/pages/[...path]/route_client-reference-manifest.js +1 -1
  33. package/.next/standalone/.next/server/app/api/files/recent/route_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/api/files/search/route_client-reference-manifest.js +1 -1
  35. package/.next/standalone/.next/server/app/api/files/spaces/[space]/pages/route.js +1 -1
  36. package/.next/standalone/.next/server/app/api/files/spaces/[space]/pages/route_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/api/files/spaces/route_client-reference-manifest.js +1 -1
  38. package/.next/standalone/.next/server/app/api/files/watch/route_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/api/gateway/detect/route_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/api/gateway/events/route_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/api/gateway/features/route_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/api/gateway/history/route_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/api/gateway/resolve/route_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/api/gateway/sessions/route_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/api/gateway/status/route_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/api/openclaw/commands/route_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/api/settings/search-status/route_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/api/setup/bootstrap/route.js +83 -1
  50. package/.next/standalone/.next/server/app/api/setup/bootstrap/route_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/api/setup/bootstrap-workspace/route.js +1 -1
  52. package/.next/standalone/.next/server/app/api/setup/bootstrap-workspace/route_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/api/setup/status/route.js +1 -1
  54. package/.next/standalone/.next/server/app/api/setup/status/route_client-reference-manifest.js +1 -1
  55. package/.next/standalone/.next/server/app/api/setup/trigger-onboarding/route.js +123 -10
  56. package/.next/standalone/.next/server/app/api/setup/trigger-onboarding/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/setup/trigger-onboarding/route_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/index.html +1 -1
  59. package/.next/standalone/.next/server/app/index.rsc +4 -4
  60. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  61. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  62. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  63. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  64. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  65. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/settings/connection/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/settings/connection.html +1 -1
  68. package/.next/standalone/.next/server/app/settings/connection.rsc +4 -4
  69. package/.next/standalone/.next/server/app/settings/connection.segments/_full.segment.rsc +4 -4
  70. package/.next/standalone/.next/server/app/settings/connection.segments/_head.segment.rsc +1 -1
  71. package/.next/standalone/.next/server/app/settings/connection.segments/_index.segment.rsc +4 -4
  72. package/.next/standalone/.next/server/app/settings/connection.segments/_tree.segment.rsc +2 -2
  73. package/.next/standalone/.next/server/app/settings/connection.segments/settings/connection/__PAGE__.segment.rsc +1 -1
  74. package/.next/standalone/.next/server/app/settings/connection.segments/settings/connection.segment.rsc +1 -1
  75. package/.next/standalone/.next/server/app/settings/connection.segments/settings.segment.rsc +1 -1
  76. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/settings.html +1 -1
  78. package/.next/standalone/.next/server/app/settings.rsc +4 -4
  79. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +4 -4
  80. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  81. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +4 -4
  82. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  83. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  84. package/.next/standalone/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  85. package/.next/standalone/.next/server/app/setup/page.js +2 -2
  86. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  87. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  88. package/.next/standalone/.next/server/app/setup.html +1 -1
  89. package/.next/standalone/.next/server/app/setup.rsc +5 -5
  90. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +5 -5
  91. package/.next/standalone/.next/server/app/setup.segments/_head.segment.rsc +1 -1
  92. package/.next/standalone/.next/server/app/setup.segments/_index.segment.rsc +4 -4
  93. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  94. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +2 -2
  95. package/.next/standalone/.next/server/app/setup.segments/setup.segment.rsc +1 -1
  96. package/.next/standalone/.next/server/app/workspace/[...path]/page.js +1 -1
  97. package/.next/standalone/.next/server/app/workspace/[...path]/page.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/workspace/[...path]/page_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/workspace/page.js +2 -2
  100. package/.next/standalone/.next/server/app/workspace/page.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/workspace/page_client-reference-manifest.js +1 -1
  102. package/.next/standalone/.next/server/app/workspace/search/page.js +2 -2
  103. package/.next/standalone/.next/server/app/workspace/search/page.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/workspace/search/page_client-reference-manifest.js +1 -1
  105. package/.next/standalone/.next/server/app/workspace/search.html +2 -2
  106. package/.next/standalone/.next/server/app/workspace/search.rsc +6 -6
  107. package/.next/standalone/.next/server/app/workspace/search.segments/_full.segment.rsc +6 -6
  108. package/.next/standalone/.next/server/app/workspace/search.segments/_head.segment.rsc +1 -1
  109. package/.next/standalone/.next/server/app/workspace/search.segments/_index.segment.rsc +4 -4
  110. package/.next/standalone/.next/server/app/workspace/search.segments/_tree.segment.rsc +2 -2
  111. package/.next/standalone/.next/server/app/workspace/search.segments/workspace/search/__PAGE__.segment.rsc +2 -2
  112. package/.next/standalone/.next/server/app/workspace/search.segments/workspace/search.segment.rsc +1 -1
  113. package/.next/standalone/.next/server/app/workspace/search.segments/workspace.segment.rsc +2 -2
  114. package/.next/standalone/.next/server/app/workspace.html +2 -2
  115. package/.next/standalone/.next/server/app/workspace.rsc +6 -6
  116. package/.next/standalone/.next/server/app/workspace.segments/_full.segment.rsc +6 -6
  117. package/.next/standalone/.next/server/app/workspace.segments/_head.segment.rsc +1 -1
  118. package/.next/standalone/.next/server/app/workspace.segments/_index.segment.rsc +4 -4
  119. package/.next/standalone/.next/server/app/workspace.segments/_tree.segment.rsc +2 -2
  120. package/.next/standalone/.next/server/app/workspace.segments/workspace/__PAGE__.segment.rsc +2 -2
  121. package/.next/standalone/.next/server/app/workspace.segments/workspace.segment.rsc +2 -2
  122. package/.next/standalone/.next/server/app-paths-manifest.json +9 -9
  123. package/.next/standalone/.next/server/chunks/2470.js +3 -3
  124. package/.next/standalone/.next/server/chunks/3251.js +2 -3
  125. package/.next/standalone/.next/server/chunks/4098.js +9 -0
  126. package/.next/standalone/.next/server/chunks/{9703.js → 7035.js} +3 -3
  127. package/.next/standalone/.next/server/chunks/7772.js +1 -0
  128. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  129. package/.next/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  130. package/.next/standalone/.next/server/pages/404.html +1 -1
  131. package/.next/standalone/.next/server/pages/500.html +2 -2
  132. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  133. package/.next/standalone/package.json +2 -1
  134. package/.next/static/chunks/1178-f2f0bd687a63b9f8.js +4 -0
  135. package/.next/static/chunks/1592-8d48cfb007c02ef4.js +9 -0
  136. package/.next/static/chunks/{4839-8d9e473f5fea81c8.js → 20-4cfa0dd1c497eee3.js} +8 -8
  137. package/.next/static/chunks/3505-9fff91cc0bc3d611.js +1 -0
  138. package/.next/static/chunks/3678.620cb571eead466f.js +1 -0
  139. package/.next/static/chunks/385-4c7c8d3ad3b6b7db.js +1 -0
  140. package/.next/static/chunks/4559-722e02df6a03e69f.js +1 -0
  141. package/.next/static/chunks/6217-dcce2b95259e116b.js +1 -0
  142. package/.next/static/chunks/app/layout-c12666d2d05cce33.js +1 -0
  143. package/.next/static/chunks/app/setup/page-7eac0e007d7fcd58.js +1 -0
  144. package/.next/static/chunks/app/workspace/[...path]/page-5c4919e22385a024.js +1 -0
  145. package/.next/static/chunks/app/workspace/layout-9717963f2fdd1346.js +6 -0
  146. package/.next/static/chunks/app/workspace/page-3869e183f908f2fc.js +1 -0
  147. package/.next/static/chunks/app/workspace/search/page-d50c5815a7c7dc09.js +1 -0
  148. package/.next/static/chunks/{ba12c10f-9f20c2943b757ccd.js → ba12c10f-d2d630b861c021fb.js} +1 -1
  149. package/.next/static/chunks/{webpack-4017efb7c7e87263.js → webpack-2f676db6328b0d7d.js} +1 -1
  150. package/.next/static/css/a44c237eaaac8354.css +1 -0
  151. package/bin/clawpad.js +174 -9
  152. package/package.json +2 -1
  153. package/public/install.sh +32 -4
  154. package/skills/README.md +40 -0
  155. package/skills/workspace-manager/SKILL.md +449 -0
  156. package/.next/standalone/.next/server/chunks/8385.js +0 -9
  157. package/.next/static/chunks/3016-27e0c450e2ada8a3.js +0 -1
  158. package/.next/static/chunks/3678.7aa2a1e7fc03b615.js +0 -1
  159. package/.next/static/chunks/5488-cb187354d8aaa3d6.js +0 -1
  160. package/.next/static/chunks/7005-2786bffdf3d8496e.js +0 -9
  161. package/.next/static/chunks/8485-4d3e303f8e277e8d.js +0 -1
  162. package/.next/static/chunks/app/layout-8a46ab4a3e2d5cb0.js +0 -4
  163. package/.next/static/chunks/app/setup/page-a2a70f253bbf4382.js +0 -1
  164. package/.next/static/chunks/app/workspace/[...path]/page-d59a1f3dbc96308f.js +0 -4
  165. package/.next/static/chunks/app/workspace/layout-504ed80ab2d05d25.js +0 -10
  166. package/.next/static/chunks/app/workspace/page-677a7fccfea3cce2.js +0 -4
  167. package/.next/static/chunks/app/workspace/search/page-c00e5c231c4a1fdd.js +0 -1
  168. package/.next/static/css/3084c1365b9c9e06.css +0 -1
  169. /package/.next/static/{wrTc1IgxHQI9epHN29OBD → WjQpy-wj7aRX-ddVHKjXc}/_buildManifest.js +0 -0
  170. /package/.next/static/{wrTc1IgxHQI9epHN29OBD → WjQpy-wj7aRX-ddVHKjXc}/_ssgManifest.js +0 -0
package/bin/clawpad.js CHANGED
@@ -20,6 +20,8 @@ const CRASH_RESTART_WINDOW_MS = 60_000;
20
20
  const MAX_CRASH_RESTARTS = 3;
21
21
  const CRASH_LOG_DIR = path.join(os.homedir(), ".clawpad", "logs");
22
22
  const CRASH_LOG_PATH = path.join(CRASH_LOG_DIR, "launcher-crashes.log");
23
+ const QMD_INSTALL_SCRIPT_URL =
24
+ "https://raw.githubusercontent.com/tobi/qmd/main/install.sh";
23
25
 
24
26
  // ─── Arg Parsing ─────────────────────────────────────────
25
27
  const args = process.argv.slice(2);
@@ -37,6 +39,7 @@ let port =
37
39
  const portExplicit = portIdx !== -1 || Boolean(process.env.PORT);
38
40
 
39
41
  const shouldOpen = !args.includes("--no-open");
42
+ const shouldSetup = args.includes("--setup");
40
43
  const shouldIntegrate = !args.includes("--no-integrate");
41
44
  const autoYes = args.includes("--yes");
42
45
  const noPrompt = args.includes("--no-prompt");
@@ -72,6 +75,7 @@ function printHelp() {
72
75
  --no-open Don't auto-open the browser
73
76
  --pages-dir <dir> Override docs directory (default: auto)
74
77
  --migrate[=mode] Migrate legacy docs (mode: move|copy)
78
+ --setup Open setup onboarding flow on launch
75
79
  --no-integrate Skip OpenClaw integration prompt
76
80
  --yes Auto-approve integration steps
77
81
  --no-prompt Disable integration prompt (skip changes)
@@ -82,6 +86,7 @@ function printHelp() {
82
86
  clawpad Start on port ${DEFAULT_PORT}
83
87
  clawpad -p 4000 Start on port 4000
84
88
  clawpad --no-open Start without opening browser
89
+ clawpad --setup Start and open setup onboarding
85
90
  clawpad --yes Auto-integrate with OpenClaw if detected
86
91
  `);
87
92
  }
@@ -676,6 +681,73 @@ function hasOpenClawBinary() {
676
681
  }
677
682
  }
678
683
 
684
+ function detectQmdBinary() {
685
+ try {
686
+ const qmdPath = execSync("command -v qmd", {
687
+ stdio: ["ignore", "pipe", "ignore"],
688
+ })
689
+ .toString()
690
+ .trim();
691
+ if (qmdPath) return qmdPath;
692
+ } catch {
693
+ // ignore
694
+ }
695
+
696
+ if (process.platform === "darwin") {
697
+ const candidate = "/opt/homebrew/bin/qmd";
698
+ if (fs.existsSync(candidate)) return candidate;
699
+ }
700
+
701
+ return null;
702
+ }
703
+
704
+ function ensureQmdInstalled() {
705
+ if (process.env.CLAWPAD_SKIP_QMD === "1") {
706
+ console.log(" ↩︎ Skipping QMD install (CLAWPAD_SKIP_QMD=1).");
707
+ return { installed: false, path: detectQmdBinary() };
708
+ }
709
+
710
+ const existing = detectQmdBinary();
711
+ if (existing) {
712
+ return { installed: true, path: existing };
713
+ }
714
+
715
+ if (process.platform === "darwin") {
716
+ try {
717
+ execSync("brew --version", { stdio: "ignore" });
718
+ console.log(" ⏳ Installing QMD with Homebrew...");
719
+ execSync("brew install qmd", { stdio: "inherit" });
720
+ } catch (err) {
721
+ const message = err && err.message ? err.message : String(err);
722
+ console.warn(` ⚠️ QMD Homebrew install failed: ${message}`);
723
+ }
724
+ } else if (process.platform === "linux") {
725
+ try {
726
+ console.log(" ⏳ Installing QMD from upstream installer...");
727
+ execSync(`curl -fsSL ${QMD_INSTALL_SCRIPT_URL} | bash`, { stdio: "inherit" });
728
+ } catch (err) {
729
+ const message = err && err.message ? err.message : String(err);
730
+ console.warn(` ⚠️ QMD installer failed: ${message}`);
731
+ }
732
+ } else {
733
+ console.log(` ↩︎ QMD auto-install not supported on ${process.platform}.`);
734
+ }
735
+
736
+ const afterInstall = detectQmdBinary();
737
+ if (afterInstall) {
738
+ return { installed: true, path: afterInstall };
739
+ }
740
+ return { installed: false, path: null };
741
+ }
742
+
743
+ function getOnboardingSentinelPath() {
744
+ return path.join(resolveOpenClawStateDir(), "clawpad", "onboarding-complete.json");
745
+ }
746
+
747
+ function hasCompletedOnboarding() {
748
+ return fs.existsSync(getOnboardingSentinelPath());
749
+ }
750
+
679
751
  function resolveWorkspaceDir(config) {
680
752
  const workspace = config?.agents?.defaults?.workspace;
681
753
  if (typeof workspace === "string" && workspace.trim()) {
@@ -719,6 +791,32 @@ function copyDir(src, dest) {
719
791
  }
720
792
  }
721
793
 
794
+ function ensureBundledSkillInstalled(workspaceDir, skillName) {
795
+ if (!workspaceDir || !skillName) {
796
+ return { installed: false, reason: "invalid-input" };
797
+ }
798
+
799
+ const bundledSkillPath = path.join(ROOT_DIR, "skills", skillName);
800
+ if (!fs.existsSync(bundledSkillPath)) {
801
+ return { installed: false, reason: "missing-bundled-skill" };
802
+ }
803
+
804
+ const skillsDir = path.join(workspaceDir, "skills");
805
+ const targetSkillPath = path.join(skillsDir, skillName);
806
+
807
+ if (fs.existsSync(targetSkillPath)) {
808
+ return { installed: false, reason: "already-installed" };
809
+ }
810
+
811
+ try {
812
+ fs.mkdirSync(skillsDir, { recursive: true });
813
+ copyDir(bundledSkillPath, targetSkillPath);
814
+ return { installed: true, reason: "installed" };
815
+ } catch (err) {
816
+ return { installed: false, reason: (err && err.message) || "copy-failed" };
817
+ }
818
+ }
819
+
722
820
  function migrateLegacyPages(fromDir, toDir, mode) {
723
821
  if (!fs.existsSync(fromDir)) {
724
822
  return { ok: false, reason: "missing" };
@@ -794,7 +892,7 @@ async function maybeMigrateLegacyPages(config, resolvedPagesDir) {
794
892
  return { pagesDir: targetDir, migrated: migrated.ok };
795
893
  }
796
894
 
797
- function applyIntegrationConfig(config, pagesDir) {
895
+ function applyIntegrationConfig(config, pagesDir, qmdPath) {
798
896
  const next = config && typeof config === "object" ? config : {};
799
897
  next.plugins = next.plugins || {};
800
898
  next.plugins.entries = next.plugins.entries || {};
@@ -810,6 +908,17 @@ function applyIntegrationConfig(config, pagesDir) {
810
908
 
811
909
  next.agents = next.agents || {};
812
910
  next.agents.defaults = next.agents.defaults || {};
911
+ const memory = next.agents.defaults.memory || {};
912
+ const memoryQmd = memory.qmd || {};
913
+ next.agents.defaults.memory = {
914
+ ...memory,
915
+ backend: "qmd",
916
+ qmd: {
917
+ ...memoryQmd,
918
+ ...(qmdPath ? { bin: qmdPath } : {}),
919
+ },
920
+ };
921
+
813
922
  const memorySearch = next.agents.defaults.memorySearch || {};
814
923
  const extraPaths = Array.isArray(memorySearch.extraPaths) ? [...memorySearch.extraPaths] : [];
815
924
  if (!extraPaths.includes(pagesDir)) {
@@ -823,18 +932,21 @@ function applyIntegrationConfig(config, pagesDir) {
823
932
  return next;
824
933
  }
825
934
 
826
- function needsIntegrationPatch(config, pagesDir) {
827
- const entry = config?.plugins?.entries?.clawpad;
935
+ function needsIntegrationPatch(config, pagesDir, qmdPath) {
936
+ const entry = config?.plugins?.entries?.["openclaw-plugin"];
828
937
  const configuredPages =
829
938
  entry?.config?.pagesDir || entry?.config?.pages_dir;
830
939
  const pluginEnabled = entry?.enabled === true;
831
940
  const extraPaths = config?.agents?.defaults?.memorySearch?.extraPaths;
832
941
  const hasExtraPath = Array.isArray(extraPaths) && extraPaths.includes(pagesDir);
942
+ const memoryBackend = config?.agents?.defaults?.memory?.backend;
943
+ const configuredQmdBin = config?.agents?.defaults?.memory?.qmd?.bin;
944
+ const qmdConfigured = memoryBackend === "qmd" && (!qmdPath || configuredQmdBin === qmdPath);
833
945
 
834
- return !(pluginEnabled && configuredPages === pagesDir && hasExtraPath);
946
+ return !(pluginEnabled && configuredPages === pagesDir && hasExtraPath && qmdConfigured);
835
947
  }
836
948
 
837
- async function integrateWithOpenClaw(pagesDir) {
949
+ async function integrateWithOpenClaw(pagesDir, qmdPath) {
838
950
  if (!shouldIntegrate) return;
839
951
  if (!hasOpenClawBinary()) return;
840
952
 
@@ -842,7 +954,12 @@ async function integrateWithOpenClaw(pagesDir) {
842
954
  const pluginInstalled = isPluginInstalled(config);
843
955
  const workspaceDir = resolveWorkspaceDir(config);
844
956
 
845
- const needsConfigPatch = needsIntegrationPatch(config, pagesDir);
957
+ const workspaceManagerSkill = ensureBundledSkillInstalled(workspaceDir, "workspace-manager");
958
+ if (workspaceManagerSkill.installed) {
959
+ console.log(" ✅ Installed workspace-manager skill in OpenClaw workspace.");
960
+ }
961
+
962
+ const needsConfigPatch = needsIntegrationPatch(config, pagesDir, qmdPath);
846
963
  const needsAgentsNote = fs.existsSync(path.join(workspaceDir, "AGENTS.md"));
847
964
 
848
965
  if (!pluginInstalled && noPrompt && !autoYes) {
@@ -867,7 +984,7 @@ async function integrateWithOpenClaw(pagesDir) {
867
984
  }
868
985
 
869
986
  if (needsConfigPatch) {
870
- const patched = applyIntegrationConfig(config, pagesDir);
987
+ const patched = applyIntegrationConfig(config, pagesDir, qmdPath);
871
988
  writeOpenClawConfig(configPath, patched);
872
989
  }
873
990
 
@@ -878,6 +995,43 @@ async function integrateWithOpenClaw(pagesDir) {
878
995
  console.log(" ✅ OpenClaw integration configured. Restart the gateway to apply.");
879
996
  }
880
997
 
998
+ function isWorkspaceEmpty(pagesDir) {
999
+ try {
1000
+ const entries = fs
1001
+ .readdirSync(pagesDir, { withFileTypes: true })
1002
+ .filter((entry) => !entry.name.startsWith("."));
1003
+ return entries.length === 0;
1004
+ } catch {
1005
+ return true;
1006
+ }
1007
+ }
1008
+
1009
+ function ensureSetupSignal(pagesDir, options = {}) {
1010
+ const signalPath = path.join(pagesDir, ".clawpad-needs-setup");
1011
+ const force = options.force === true;
1012
+
1013
+ try {
1014
+ fs.mkdirSync(pagesDir, { recursive: true });
1015
+
1016
+ if (!force && hasCompletedOnboarding()) {
1017
+ return false;
1018
+ }
1019
+
1020
+ if (!force && !isWorkspaceEmpty(pagesDir)) {
1021
+ return false;
1022
+ }
1023
+
1024
+ const payload = {
1025
+ created: new Date().toISOString(),
1026
+ reason: force ? "cli-setup-flag" : "first-run-empty-workspace",
1027
+ };
1028
+ fs.writeFileSync(signalPath, JSON.stringify(payload, null, 2), "utf-8");
1029
+ return true;
1030
+ } catch {
1031
+ return false;
1032
+ }
1033
+ }
1034
+
881
1035
  // ─── Build Check ─────────────────────────────────────────
882
1036
  function isBuilt() {
883
1037
  const standaloneServer = path.join(ROOT_DIR, ".next", "standalone", "server.js");
@@ -973,7 +1127,17 @@ async function main() {
973
1127
  if (!process.env.CLAWPAD_PAGES_DIR && pagesDir) {
974
1128
  process.env.CLAWPAD_PAGES_DIR = pagesDir;
975
1129
  }
976
- await integrateWithOpenClaw(pagesDir);
1130
+ const qmd = ensureQmdInstalled();
1131
+ if (qmd.installed && qmd.path) {
1132
+ console.log(` ✅ QMD available at ${qmd.path}`);
1133
+ } else {
1134
+ console.log(" ⚠️ QMD unavailable. Semantic search and QMD memory backend may be limited.");
1135
+ }
1136
+ await integrateWithOpenClaw(pagesDir, qmd.path);
1137
+ const setupSignalCreated = ensureSetupSignal(pagesDir, { force: shouldSetup });
1138
+ if (setupSignalCreated) {
1139
+ console.log(" 📝 Setup signal detected. ClawPad will open onboarding.");
1140
+ }
977
1141
 
978
1142
  // Build if needed
979
1143
  if (!isBuilt()) {
@@ -1071,7 +1235,8 @@ async function main() {
1071
1235
  const launchServer = (nextPort) => {
1072
1236
  port = nextPort;
1073
1237
  const runningPort = nextPort;
1074
- const url = `http://localhost:${port}`;
1238
+ const setupPath = shouldSetup || setupSignalCreated ? "/setup" : "";
1239
+ const url = `http://localhost:${port}${setupPath}`;
1075
1240
  console.log(` 🚀 Starting ClawPad at ${url}\n`);
1076
1241
 
1077
1242
  let sawAddrInUse = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawpad",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "A file-based, Notion-style document workspace for OpenClaw",
5
5
  "keywords": [
6
6
  "openclaw",
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "files": [
28
28
  "bin/",
29
+ "skills/",
29
30
  ".next/standalone/",
30
31
  ".next/static/",
31
32
  "public/",
package/public/install.sh CHANGED
@@ -9,7 +9,7 @@ INSTALL_PREFIX="${CLAWPAD_PREFIX:-$HOME/.local}"
9
9
  INSTALL_TIMEOUT_SECONDS="${CLAWPAD_INSTALL_TIMEOUT_SECONDS:-180}"
10
10
 
11
11
  echo "ClawPad installer"
12
- echo "[1/4] Checking Node.js..."
12
+ echo "[1/5] Checking Node.js..."
13
13
 
14
14
  if ! command -v node >/dev/null 2>&1; then
15
15
  echo "ClawPad requires Node.js ${MIN_NODE_MAJOR}+." >&2
@@ -28,7 +28,7 @@ if ! command -v npm >/dev/null 2>&1; then
28
28
  exit 1
29
29
  fi
30
30
 
31
- echo "[2/4] Preparing install prefix: ${INSTALL_PREFIX}"
31
+ echo "[2/5] Preparing install prefix: ${INSTALL_PREFIX}"
32
32
  mkdir -p "${INSTALL_PREFIX}/bin"
33
33
 
34
34
  # Make npm quieter and avoid long post-install checks
@@ -37,7 +37,7 @@ export NPM_CONFIG_AUDIT=false
37
37
  export NPM_CONFIG_UPDATE_NOTIFIER=false
38
38
  export NPM_CONFIG_PROGRESS=false
39
39
 
40
- echo "[3/4] Installing ClawPad (this can take a minute)..."
40
+ echo "[3/5] Installing ClawPad (this can take a minute)..."
41
41
 
42
42
  # Install clawpad CLI into user prefix
43
43
  install_args=(install -g clawpad --prefix "${INSTALL_PREFIX}")
@@ -65,8 +65,36 @@ if [ "${install_exit}" -ne 0 ]; then
65
65
  exit "${install_exit}"
66
66
  fi
67
67
 
68
+ # Best-effort QMD install
69
+ echo "[4/5] Checking QMD (best-effort)"
70
+ if [ "${CLAWPAD_SKIP_QMD:-0}" = "1" ]; then
71
+ echo "Skipping QMD install (CLAWPAD_SKIP_QMD=1)."
72
+ elif command -v qmd >/dev/null 2>&1; then
73
+ echo "QMD already installed."
74
+ elif [ "$(uname -s)" = "Darwin" ] && command -v brew >/dev/null 2>&1; then
75
+ if brew install qmd; then
76
+ echo "QMD installed with Homebrew."
77
+ else
78
+ echo "QMD install failed via Homebrew (continuing)." >&2
79
+ fi
80
+ elif [ "$(uname -s)" = "Linux" ] && command -v curl >/dev/null 2>&1; then
81
+ if curl -fsSL https://raw.githubusercontent.com/tobi/qmd/main/install.sh | bash; then
82
+ echo "QMD installed from upstream installer."
83
+ else
84
+ echo "QMD install failed via upstream script (continuing)." >&2
85
+ fi
86
+ else
87
+ echo "QMD auto-install skipped: unsupported platform or missing installer dependency."
88
+ fi
89
+
90
+ if command -v qmd >/dev/null 2>&1; then
91
+ echo "QMD ready: $(qmd --version 2>/dev/null || echo qmd)"
92
+ else
93
+ echo "QMD unavailable. You can install it later for semantic search."
94
+ fi
95
+
68
96
  # Add prefix bin to PATH if needed
69
- echo "[4/4] Finalizing PATH setup"
97
+ echo "[5/5] Finalizing PATH setup"
70
98
  if ! echo "$PATH" | grep -q "${INSTALL_PREFIX}/bin"; then
71
99
  if [ -f "$HOME/.bashrc" ]; then
72
100
  echo "export PATH=\"${INSTALL_PREFIX}/bin:\$PATH\"" >> "$HOME/.bashrc"
@@ -0,0 +1,40 @@
1
+ # ClawPad Skills
2
+
3
+ Community skills for enhancing ClawPad workspaces.
4
+
5
+ ## Available Skills
6
+
7
+ | Skill | Description |
8
+ |-------|-------------|
9
+ | [workspace-manager](./workspace-manager/) | Workspace setup and organization assistant. Helps users create personalized folder structures based on their domain (engineering, research, business, creative, personal). |
10
+
11
+ ## Installing Skills
12
+
13
+ Skills are automatically discovered by OpenClaw from `~/.openclaw/workspace/skills/`.
14
+
15
+ To install a skill:
16
+
17
+ ```bash
18
+ # Copy the skill folder to your OpenClaw workspace
19
+ cp -r skills/workspace-manager ~/.openclaw/workspace/skills/
20
+ ```
21
+
22
+ Or symlink for development:
23
+
24
+ ```bash
25
+ ln -s $(pwd)/skills/workspace-manager ~/.openclaw/workspace/skills/workspace-manager
26
+ ```
27
+
28
+ ## Creating Skills
29
+
30
+ See [OpenClaw Skills Documentation](https://docs.openclaw.ai/skills) for the full guide.
31
+
32
+ Basic structure:
33
+ ```
34
+ skills/
35
+ └── your-skill/
36
+ ├── SKILL.md # Main skill definition (required)
37
+ └── references/ # Optional supporting files
38
+ ```
39
+
40
+ The `SKILL.md` file should have YAML frontmatter with `name` and `description`, followed by markdown instructions for the agent.