claude-kanban 0.6.1 → 0.6.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.
package/dist/bin/cli.js CHANGED
@@ -1841,11 +1841,33 @@ var RoadmapService = class extends EventEmitter2 {
1841
1841
  let description = "";
1842
1842
  let stack = [];
1843
1843
  let existingFeatures = [];
1844
+ const claudeMdPaths = ["CLAUDE.md", "claude.md", ".claude/CLAUDE.md"];
1845
+ for (const claudePath of claudeMdPaths) {
1846
+ const fullPath = join5(this.projectPath, claudePath);
1847
+ if (existsSync3(fullPath)) {
1848
+ const claudeMd = readFileSync5(fullPath, "utf-8");
1849
+ const lines = claudeMd.split("\n");
1850
+ const contentLines = [];
1851
+ for (const line of lines) {
1852
+ const trimmed = line.trim();
1853
+ if (trimmed && !trimmed.startsWith("#") && !trimmed.startsWith("```")) {
1854
+ contentLines.push(trimmed);
1855
+ if (contentLines.join(" ").length > 300) break;
1856
+ }
1857
+ }
1858
+ if (contentLines.length > 0) {
1859
+ description = contentLines.join(" ").slice(0, 500);
1860
+ }
1861
+ break;
1862
+ }
1863
+ }
1844
1864
  const packageJsonPath = join5(this.projectPath, "package.json");
1845
1865
  if (existsSync3(packageJsonPath)) {
1846
1866
  try {
1847
1867
  const pkg = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
1848
- description = pkg.description || "";
1868
+ if (!description && pkg.description && !pkg.description.includes("<")) {
1869
+ description = pkg.description;
1870
+ }
1849
1871
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1850
1872
  if (deps.react) stack.push("React");
1851
1873
  if (deps.vue) stack.push("Vue");
@@ -1855,23 +1877,43 @@ var RoadmapService = class extends EventEmitter2 {
1855
1877
  if (deps.fastify) stack.push("Fastify");
1856
1878
  if (deps.typescript) stack.push("TypeScript");
1857
1879
  if (deps.tailwindcss) stack.push("Tailwind CSS");
1880
+ if (deps.laravel) stack.push("Laravel");
1858
1881
  } catch {
1859
1882
  }
1860
1883
  }
1861
- const readmePaths = ["README.md", "readme.md", "README.txt", "readme.txt"];
1862
- for (const readmePath of readmePaths) {
1863
- const fullPath = join5(this.projectPath, readmePath);
1864
- if (existsSync3(fullPath)) {
1865
- const readme = readFileSync5(fullPath, "utf-8");
1866
- if (!description) {
1867
- const lines = readme.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
1884
+ const composerPath = join5(this.projectPath, "composer.json");
1885
+ if (existsSync3(composerPath)) {
1886
+ try {
1887
+ const composer = JSON.parse(readFileSync5(composerPath, "utf-8"));
1888
+ if (!description && composer.description && !composer.description.includes("<")) {
1889
+ description = composer.description;
1890
+ }
1891
+ if (composer.require?.["laravel/framework"]) stack.push("Laravel");
1892
+ if (composer.require?.["livewire/livewire"]) stack.push("Livewire");
1893
+ if (composer.require?.["inertiajs/inertia-laravel"]) stack.push("Inertia.js");
1894
+ } catch {
1895
+ }
1896
+ }
1897
+ if (!description) {
1898
+ const readmePaths = ["README.md", "readme.md", "README.txt", "readme.txt"];
1899
+ for (const readmePath of readmePaths) {
1900
+ const fullPath = join5(this.projectPath, readmePath);
1901
+ if (existsSync3(fullPath)) {
1902
+ const readme = readFileSync5(fullPath, "utf-8");
1903
+ const lines = readme.split("\n").filter((l) => {
1904
+ const trimmed = l.trim();
1905
+ return trimmed && !trimmed.startsWith("#") && !trimmed.startsWith("<") && !trimmed.startsWith("![") && !trimmed.startsWith("[!");
1906
+ });
1868
1907
  if (lines.length > 0) {
1869
1908
  description = lines[0].trim().slice(0, 500);
1870
1909
  }
1910
+ break;
1871
1911
  }
1872
- break;
1873
1912
  }
1874
1913
  }
1914
+ if (!description) {
1915
+ description = `A ${stack.length > 0 ? stack.join("/") + " " : ""}software project`;
1916
+ }
1875
1917
  const prdPath = join5(this.projectPath, ROADMAP_DIR, "prd.json");
1876
1918
  if (existsSync3(prdPath)) {
1877
1919
  try {
@@ -1956,19 +1998,24 @@ var RoadmapService = class extends EventEmitter2 {
1956
1998
  * Build the competitor research prompt
1957
1999
  */
1958
2000
  buildCompetitorResearchPrompt(projectInfo) {
1959
- return `You are a product research analyst. Research competitors for the following project:
2001
+ return `You are a product research analyst. Your task is to research competitors and return ONLY JSON output.
1960
2002
 
1961
- Project: ${projectInfo.name}
1962
- Description: ${projectInfo.description}
1963
- Tech Stack: ${projectInfo.stack.join(", ") || "Unknown"}
2003
+ IMPORTANT: Do not ask any questions. Do not request clarification. Just analyze and return the JSON.
1964
2004
 
1965
- Your task:
1966
- 1. Use web search to find 3-5 competitors or similar projects
1967
- 2. Analyze their strengths and weaknesses
1968
- 3. Identify differentiating features
2005
+ ## Project Information
2006
+ - Name: ${projectInfo.name}
2007
+ - Description: ${projectInfo.description}
2008
+ - Tech Stack: ${projectInfo.stack.join(", ") || "Unknown"}
2009
+
2010
+ ## Your Task
2011
+ 1. Based on the project description, identify what type of product/service this is
2012
+ 2. Find 3-5 competitors or similar projects in this space
2013
+ 3. Analyze their strengths and weaknesses
2014
+ 4. Identify differentiating features
2015
+
2016
+ ## Required Output Format
2017
+ Return ONLY a JSON array (no markdown code blocks, no explanations):
1969
2018
 
1970
- Return your findings as JSON in this format:
1971
- \`\`\`json
1972
2019
  [
1973
2020
  {
1974
2021
  "name": "Competitor Name",
@@ -1978,9 +2025,8 @@ Return your findings as JSON in this format:
1978
2025
  "differentiators": ["feature 1", "feature 2"]
1979
2026
  }
1980
2027
  ]
1981
- \`\`\`
1982
2028
 
1983
- Only return the JSON, no other text.`;
2029
+ Begin your response with [ and end with ]. No other text.`;
1984
2030
  }
1985
2031
  /**
1986
2032
  * Build the roadmap generation prompt
@@ -2020,7 +2066,9 @@ ${request.customPrompt}
2020
2066
  `;
2021
2067
  }
2022
2068
  prompt += `
2023
- ## Your Task
2069
+ ## Instructions
2070
+ IMPORTANT: Do not ask any questions. Do not request clarification. Generate the roadmap based on the information provided.
2071
+
2024
2072
  Create a comprehensive product roadmap with features organized into phases.
2025
2073
 
2026
2074
  Use the MoSCoW prioritization framework:
@@ -2035,8 +2083,9 @@ For each feature, estimate:
2035
2083
 
2036
2084
  Categories should be one of: functional, ui, bug, enhancement, testing, refactor
2037
2085
 
2038
- Return your roadmap as JSON:
2039
- \`\`\`json
2086
+ ## Required Output Format
2087
+ Return ONLY valid JSON (no markdown code blocks, no explanations). Begin with { and end with }:
2088
+
2040
2089
  {
2041
2090
  "projectDescription": "Brief description of the project",
2042
2091
  "targetAudience": "Who this project is for",
@@ -2064,11 +2113,10 @@ Return your roadmap as JSON:
2064
2113
  }
2065
2114
  ]
2066
2115
  }
2067
- \`\`\`
2068
2116
 
2069
2117
  Generate 10-20 strategic features across 3-4 phases. Be specific and actionable.
2070
2118
  Don't duplicate features that already exist in the project.
2071
- Only return the JSON, no other text.`;
2119
+ Begin your response with { - no other text before or after the JSON.`;
2072
2120
  return prompt;
2073
2121
  }
2074
2122
  /**
@@ -4273,33 +4321,33 @@ function renderRoadmapFeature(feature) {
4273
4321
 
4274
4322
  function renderRoadmapModal() {
4275
4323
  return \`
4276
- <div class="modal-backdrop" onclick="state.showModal = null; render();">
4277
- <div class="modal-content max-w-lg" onclick="event.stopPropagation();">
4278
- <div class="modal-header">
4279
- <h2 class="modal-title">Generate Roadmap</h2>
4280
- <button onclick="state.showModal = null; render();" class="modal-close">\xD7</button>
4324
+ <div class="modal-backdrop fixed inset-0 flex items-center justify-center z-50" onclick="if(event.target === event.currentTarget) { state.showModal = null; render(); }">
4325
+ <div class="modal-content card rounded-xl w-full max-w-lg mx-4">
4326
+ <div class="px-6 py-4 border-b border-canvas-200 flex justify-between items-center">
4327
+ <h3 class="font-display font-semibold text-canvas-800 text-lg">\u{1F5FA}\uFE0F Generate Roadmap</h3>
4328
+ <button onclick="state.showModal = null; render();" class="text-canvas-400 hover:text-canvas-600 text-xl leading-none">&times;</button>
4281
4329
  </div>
4282
- <div class="modal-body">
4283
- <p class="text-sm text-canvas-500 mb-4">
4330
+ <div class="p-6">
4331
+ <p class="text-sm text-canvas-500 mb-6">
4284
4332
  Generate a strategic feature roadmap by analyzing your project structure and optionally researching competitors.
4285
4333
  </p>
4286
4334
 
4287
- <div class="space-y-4">
4288
- <label class="flex items-center gap-3 cursor-pointer">
4335
+ <div class="space-y-5">
4336
+ <label class="flex items-start gap-3 cursor-pointer p-3 rounded-lg border border-canvas-200 hover:border-canvas-300 transition-colors">
4289
4337
  <input type="checkbox"
4290
4338
  \${state.roadmapEnableCompetitors ? 'checked' : ''}
4291
4339
  onchange="state.roadmapEnableCompetitors = this.checked; render();"
4292
- class="w-4 h-4 accent-accent">
4340
+ class="w-4 h-4 mt-0.5 accent-accent">
4293
4341
  <div>
4294
4342
  <span class="text-sm font-medium text-canvas-700">Enable competitor research</span>
4295
- <p class="text-xs text-canvas-400">Use web search to analyze competitors (takes longer)</p>
4343
+ <p class="text-xs text-canvas-400 mt-0.5">Use web search to analyze competitors (takes longer)</p>
4296
4344
  </div>
4297
4345
  </label>
4298
4346
 
4299
4347
  <div>
4300
- <label class="text-sm font-medium text-canvas-700">Additional context (optional)</label>
4348
+ <label class="block text-sm font-medium text-canvas-700 mb-1.5">Additional context (optional)</label>
4301
4349
  <textarea
4302
- class="input w-full mt-1 text-sm"
4350
+ class="input w-full text-sm"
4303
4351
  rows="3"
4304
4352
  placeholder="E.g., Focus on mobile features, target enterprise users..."
4305
4353
  oninput="state.roadmapCustomPrompt = this.value;"
@@ -4307,9 +4355,9 @@ function renderRoadmapModal() {
4307
4355
  </div>
4308
4356
  </div>
4309
4357
  </div>
4310
- <div class="modal-footer">
4311
- <button onclick="state.showModal = null; render();" class="btn btn-ghost">Cancel</button>
4312
- <button onclick="generateRoadmap(); state.showModal = null; render();" class="btn btn-primary">
4358
+ <div class="px-6 py-4 border-t border-canvas-200 flex justify-end gap-3">
4359
+ <button onclick="state.showModal = null; render();" class="btn btn-ghost px-4 py-2">Cancel</button>
4360
+ <button onclick="generateRoadmap(); state.showModal = null; render();" class="btn btn-primary px-4 py-2">
4313
4361
  \u{1F680} Generate Roadmap
4314
4362
  </button>
4315
4363
  </div>