@pikaa-ai/pikaa 0.3.11 → 0.3.12

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 (2) hide show
  1. package/dist/cli.js +114 -102
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6043,7 +6043,7 @@ function parsePatch(oldSrc, newSrc, contextLines = 3) {
6043
6043
  // package.json
6044
6044
  var package_default = {
6045
6045
  name: "@pikaa-ai/pikaa",
6046
- version: "0.3.11",
6046
+ version: "0.3.12",
6047
6047
  description: "PIKAA CLI - AI coding agent that runs locally in your terminal.",
6048
6048
  main: "./dist/index.js",
6049
6049
  module: "./dist/index.js",
@@ -7767,7 +7767,7 @@ var __dirname = "/home/runner/work/agent-cli/agent-cli/src/mcp/servers/sqlite";
7767
7767
  var SQLITE_MCP_SERVER_PATH = resolve20(__dirname, "server.ts");
7768
7768
 
7769
7769
  // src/init/project-analyzer.ts
7770
- import { existsSync as existsSync18, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
7770
+ import { existsSync as existsSync18, readFileSync as readFileSync13, readdirSync as readdirSync6 } from "fs";
7771
7771
  import { join as join9, basename as basename2 } from "path";
7772
7772
 
7773
7773
  class ProjectAnalyzer {
@@ -7776,23 +7776,30 @@ class ProjectAnalyzer {
7776
7776
  this.cwd = cwd;
7777
7777
  }
7778
7778
  analyze() {
7779
- const projectName = this.detectProjectName();
7779
+ const readmeInfo = this.extractReadmeMetadata();
7780
+ const projectName = readmeInfo.title || this.detectProjectName();
7780
7781
  const languages = this.detectLanguages();
7781
7782
  const packageManager = this.detectPackageManager();
7782
7783
  const frameworks = [];
7784
+ const infrastructure = [];
7783
7785
  const commands = {};
7786
+ const architectureNotes = [];
7784
7787
  const codeConventions = [];
7785
- let description;
7788
+ let description = readmeInfo.description;
7786
7789
  const pkgPath = join9(this.cwd, "package.json");
7787
7790
  if (existsSync18(pkgPath)) {
7788
7791
  try {
7789
7792
  const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
7790
- if (pkg.description)
7793
+ if (!description && pkg.description)
7791
7794
  description = pkg.description;
7792
7795
  const pm = packageManager || "npm";
7793
7796
  const runPrefix = pm === "bun" || pm === "yarn" || pm === "pnpm" ? `${pm} run` : "npm run";
7794
7797
  const testPrefix = pm === "bun" ? "bun test" : pm === "pnpm" ? "pnpm test" : pm === "yarn" ? "yarn test" : "npm test";
7795
7798
  if (pkg.scripts) {
7799
+ if (pkg.scripts.dev)
7800
+ commands.dev = `${runPrefix} dev`;
7801
+ else if (pkg.scripts.start)
7802
+ commands.dev = `${runPrefix} start`;
7796
7803
  if (pkg.scripts.build)
7797
7804
  commands.build = `${runPrefix} build`;
7798
7805
  if (pkg.scripts.test)
@@ -7803,10 +7810,6 @@ class ProjectAnalyzer {
7803
7810
  commands.typecheck = `${runPrefix} check`;
7804
7811
  if (pkg.scripts.lint)
7805
7812
  commands.lint = `${runPrefix} lint`;
7806
- if (pkg.scripts.dev)
7807
- commands.dev = `${runPrefix} dev`;
7808
- else if (pkg.scripts.start)
7809
- commands.dev = `${runPrefix} start`;
7810
7813
  if (pkg.scripts.format)
7811
7814
  commands.format = `${runPrefix} format`;
7812
7815
  }
@@ -7824,6 +7827,8 @@ class ProjectAnalyzer {
7824
7827
  frameworks.push("Svelte");
7825
7828
  if (allDeps.astro)
7826
7829
  frameworks.push("Astro");
7830
+ if (allDeps.vite)
7831
+ frameworks.push("Vite");
7827
7832
  if (allDeps.express)
7828
7833
  frameworks.push("Express");
7829
7834
  if (allDeps.hono)
@@ -7834,6 +7839,16 @@ class ProjectAnalyzer {
7834
7839
  frameworks.push("NestJS");
7835
7840
  if (allDeps.tailwindcss)
7836
7841
  frameworks.push("TailwindCSS");
7842
+ if (allDeps["lucide-react"] || allDeps.lucide)
7843
+ frameworks.push("Lucide Icons");
7844
+ if (allDeps.zustand)
7845
+ frameworks.push("Zustand");
7846
+ if (allDeps["@tanstack/react-query"])
7847
+ frameworks.push("TanStack Query");
7848
+ if (allDeps.oxlint)
7849
+ frameworks.push("Oxlint");
7850
+ if (allDeps.eslint)
7851
+ frameworks.push("ESLint");
7837
7852
  if (allDeps.vitest)
7838
7853
  frameworks.push("Vitest");
7839
7854
  if (allDeps.jest)
@@ -7841,9 +7856,7 @@ class ProjectAnalyzer {
7841
7856
  if (allDeps.playwright || allDeps["@playwright/test"])
7842
7857
  frameworks.push("Playwright");
7843
7858
  if (pkg.type === "module") {
7844
- codeConventions.push('ES Modules enabled (`"type": "module"`)');
7845
- } else {
7846
- codeConventions.push("CommonJS module format");
7859
+ codeConventions.push("Use ES modules (`import/export`), not CommonJS (`require`).");
7847
7860
  }
7848
7861
  } catch {}
7849
7862
  }
@@ -7852,7 +7865,7 @@ class ProjectAnalyzer {
7852
7865
  try {
7853
7866
  const tsconfig = JSON.parse(readFileSync13(tsconfigPath, "utf8"));
7854
7867
  if (tsconfig.compilerOptions?.strict) {
7855
- codeConventions.push("TypeScript Strict Mode enabled");
7868
+ codeConventions.push("TypeScript strict mode enabled.");
7856
7869
  }
7857
7870
  if (!commands.typecheck) {
7858
7871
  commands.typecheck = "tsc --noEmit";
@@ -7862,34 +7875,21 @@ class ProjectAnalyzer {
7862
7875
  const cargoPath = join9(this.cwd, "Cargo.toml");
7863
7876
  if (existsSync18(cargoPath)) {
7864
7877
  try {
7865
- const content = readFileSync13(cargoPath, "utf8");
7878
+ commands.dev = commands.dev || "cargo run";
7866
7879
  commands.build = commands.build || "cargo build";
7867
7880
  commands.test = commands.test || "cargo test";
7868
7881
  commands.lint = commands.lint || "cargo clippy";
7869
- commands.dev = commands.dev || "cargo run";
7870
- if (content.includes('edition = "2021"')) {
7871
- codeConventions.push("Rust 2021 Edition");
7872
- }
7873
- if (content.includes("tokio"))
7874
- frameworks.push("Tokio (Async Runtime)");
7875
- if (content.includes("axum"))
7876
- frameworks.push("Axum");
7877
- if (content.includes("actix-web"))
7878
- frameworks.push("Actix-Web");
7882
+ frameworks.push("Rust Cargo");
7879
7883
  } catch {}
7880
7884
  }
7881
7885
  const goModPath = join9(this.cwd, "go.mod");
7882
7886
  if (existsSync18(goModPath)) {
7883
7887
  try {
7884
- const content = readFileSync13(goModPath, "utf8");
7888
+ commands.dev = commands.dev || "go run .";
7885
7889
  commands.build = commands.build || "go build ./...";
7886
7890
  commands.test = commands.test || "go test ./...";
7887
7891
  commands.lint = commands.lint || "golangci-lint run";
7888
- commands.dev = commands.dev || "go run .";
7889
- const goVer = content.match(/go\s+(\d+\.\d+)/);
7890
- if (goVer?.[1]) {
7891
- codeConventions.push(`Go ${goVer[1]}`);
7892
- }
7892
+ frameworks.push("Go Modules");
7893
7893
  } catch {}
7894
7894
  }
7895
7895
  const pyprojectPath = join9(this.cwd, "pyproject.toml");
@@ -7897,16 +7897,44 @@ class ProjectAnalyzer {
7897
7897
  if (existsSync18(pyprojectPath) || existsSync18(requirementsPath)) {
7898
7898
  commands.test = commands.test || "pytest";
7899
7899
  commands.lint = commands.lint || "ruff check .";
7900
- commands.format = commands.format || "black .";
7901
7900
  if (existsSync18(join9(this.cwd, "uv.lock"))) {
7902
- codeConventions.push("uv package & project manager");
7901
+ frameworks.push("uv");
7903
7902
  commands.test = "uv run pytest";
7904
7903
  } else if (existsSync18(join9(this.cwd, "poetry.lock"))) {
7905
- codeConventions.push("Poetry dependency manager");
7904
+ frameworks.push("Poetry");
7906
7905
  commands.test = "poetry run pytest";
7907
7906
  }
7908
7907
  }
7909
- const directoryStructure = this.scanDirectoryStructure();
7908
+ if (existsSync18(join9(this.cwd, "Dockerfile"))) {
7909
+ infrastructure.push("Docker");
7910
+ const sanitizedName = projectName.toLowerCase().replace(/[^a-z0-9_-]/g, "-").replace(/^-+|-+$/g, "");
7911
+ commands.dockerBuild = `docker build -t ${sanitizedName || "app"} .`;
7912
+ }
7913
+ if (existsSync18(join9(this.cwd, "nginx.conf"))) {
7914
+ infrastructure.push("Nginx");
7915
+ }
7916
+ if (existsSync18(join9(this.cwd, "src/api.ts")) || existsSync18(join9(this.cwd, "src/api"))) {
7917
+ architectureNotes.push("Backend API endpoints and network client logic are centralized in `src/api`.");
7918
+ }
7919
+ if (existsSync18(join9(this.cwd, "src/components"))) {
7920
+ architectureNotes.push("Reusable UI presentation components live in `src/components/`.");
7921
+ }
7922
+ if (existsSync18(join9(this.cwd, "src/types.ts")) || existsSync18(join9(this.cwd, "src/types"))) {
7923
+ architectureNotes.push("Shared TypeScript data models and interfaces are defined in `src/types`.");
7924
+ }
7925
+ if (existsSync18(join9(this.cwd, ".env.example"))) {
7926
+ architectureNotes.push("Environment configuration template is in `.env.example`.");
7927
+ }
7928
+ if (commands.typecheck || commands.lint || commands.test) {
7929
+ const checks = [];
7930
+ if (commands.typecheck)
7931
+ checks.push(`typecheck (\`${commands.typecheck}\`)`);
7932
+ if (commands.lint)
7933
+ checks.push(`lint (\`${commands.lint}\`)`);
7934
+ if (commands.test)
7935
+ checks.push(`tests (\`${commands.test}\`)`);
7936
+ codeConventions.push(`Run ${checks.join(" and ")} before concluding any major code edits.`);
7937
+ }
7910
7938
  const instructionFiles = ["AGENTS.md", "CLAUDE.md", ".agents.md", "AGENTS.override.md"];
7911
7939
  let hasExistingInstructions = false;
7912
7940
  let existingInstructionFile;
@@ -7923,8 +7951,9 @@ class ProjectAnalyzer {
7923
7951
  languages,
7924
7952
  packageManager,
7925
7953
  frameworks,
7954
+ infrastructure,
7926
7955
  commands,
7927
- directoryStructure,
7956
+ architectureNotes,
7928
7957
  codeConventions,
7929
7958
  hasExistingInstructions,
7930
7959
  existingInstructionFile
@@ -7938,21 +7967,11 @@ class ProjectAnalyzer {
7938
7967
  lines.push(`> ${analysis.description}`);
7939
7968
  lines.push("");
7940
7969
  }
7941
- lines.push("## Tech Stack");
7942
- lines.push("");
7943
- if (analysis.languages.length > 0) {
7944
- lines.push(`- **Languages**: ${analysis.languages.join(", ")}`);
7945
- }
7946
- if (analysis.packageManager) {
7947
- lines.push(`- **Package Manager**: ${analysis.packageManager}`);
7948
- }
7949
- if (analysis.frameworks.length > 0) {
7950
- lines.push(`- **Frameworks & Libraries**: ${analysis.frameworks.join(", ")}`);
7951
- }
7952
- lines.push("");
7953
- lines.push("## Development Commands");
7970
+ lines.push("## Commands");
7954
7971
  lines.push("");
7955
7972
  if (Object.keys(analysis.commands).length > 0) {
7973
+ if (analysis.commands.dev)
7974
+ lines.push(`- **Dev Server**: \`${analysis.commands.dev}\``);
7956
7975
  if (analysis.commands.build)
7957
7976
  lines.push(`- **Build**: \`${analysis.commands.build}\``);
7958
7977
  if (analysis.commands.test)
@@ -7961,44 +7980,77 @@ class ProjectAnalyzer {
7961
7980
  lines.push(`- **Typecheck**: \`${analysis.commands.typecheck}\``);
7962
7981
  if (analysis.commands.lint)
7963
7982
  lines.push(`- **Lint**: \`${analysis.commands.lint}\``);
7964
- if (analysis.commands.dev)
7965
- lines.push(`- **Dev / Run**: \`${analysis.commands.dev}\``);
7966
7983
  if (analysis.commands.format)
7967
7984
  lines.push(`- **Format**: \`${analysis.commands.format}\``);
7985
+ if (analysis.commands.dockerBuild)
7986
+ lines.push(`- **Docker Build**: \`${analysis.commands.dockerBuild}\``);
7968
7987
  } else {
7969
7988
  lines.push("- *No standard build/test commands detected.*");
7970
7989
  }
7971
7990
  lines.push("");
7972
- lines.push("## Architecture & Directory Structure");
7991
+ lines.push("## Architecture & Stack");
7973
7992
  lines.push("");
7974
- if (Object.keys(analysis.directoryStructure).length > 0) {
7975
- for (const [dir, purpose] of Object.entries(analysis.directoryStructure)) {
7976
- lines.push(`- \`${dir}\`: ${purpose}`);
7977
- }
7978
- } else {
7979
- lines.push("- Root project workspace");
7993
+ const stackItems = [];
7994
+ if (analysis.languages.length > 0)
7995
+ stackItems.push(analysis.languages.join(", "));
7996
+ if (analysis.frameworks.length > 0)
7997
+ stackItems.push(analysis.frameworks.join(", "));
7998
+ if (analysis.infrastructure.length > 0)
7999
+ stackItems.push(analysis.infrastructure.join(", "));
8000
+ if (stackItems.length > 0) {
8001
+ lines.push(`- **Core Stack**: ${stackItems.join(" \u2022 ")}`);
8002
+ }
8003
+ for (const note of analysis.architectureNotes) {
8004
+ lines.push(`- ${note}`);
7980
8005
  }
7981
8006
  lines.push("");
7982
- lines.push("## Code Style & Guidelines");
8007
+ lines.push("## Workflow & Code Guidelines");
7983
8008
  lines.push("");
7984
8009
  if (analysis.codeConventions.length > 0) {
7985
8010
  for (const conv of analysis.codeConventions) {
7986
8011
  lines.push(`- ${conv}`);
7987
8012
  }
7988
8013
  }
7989
- lines.push("- Keep functions focused and modular.");
7990
- lines.push("- Maintain clean error handling and avoid unhandled exceptions.");
7991
- lines.push("- Run automated test suite before completing major code changes.");
8014
+ lines.push("- Prefer targeted edits over whole-file rewrites.");
8015
+ lines.push("- When fixing errors, address the root cause rather than suppressing compiler warnings.");
7992
8016
  lines.push("");
7993
8017
  return lines.join(`
7994
8018
  `);
7995
8019
  }
8020
+ extractReadmeMetadata() {
8021
+ const readmeFiles = ["README.md", "readme.md", "README.MD"];
8022
+ for (const file of readmeFiles) {
8023
+ const fullPath = join9(this.cwd, file);
8024
+ if (existsSync18(fullPath)) {
8025
+ try {
8026
+ const content = readFileSync13(fullPath, "utf8");
8027
+ const lines = content.split(`
8028
+ `);
8029
+ let title;
8030
+ let description;
8031
+ for (const line of lines) {
8032
+ const trimmed = line.trim();
8033
+ if (!title && trimmed.startsWith("# ")) {
8034
+ title = trimmed.replace(/^#\s+/, "").trim();
8035
+ continue;
8036
+ }
8037
+ if (title && !description && trimmed.length > 0 && !trimmed.startsWith("#") && !trimmed.startsWith("```") && !trimmed.startsWith("[")) {
8038
+ description = trimmed;
8039
+ break;
8040
+ }
8041
+ }
8042
+ return { title, description };
8043
+ } catch {}
8044
+ }
8045
+ }
8046
+ return {};
8047
+ }
7996
8048
  detectProjectName() {
7997
8049
  const pkgPath = join9(this.cwd, "package.json");
7998
8050
  if (existsSync18(pkgPath)) {
7999
8051
  try {
8000
8052
  const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
8001
- if (pkg.name) {
8053
+ if (pkg.name && pkg.name !== "frontend" && pkg.name !== "backend" && pkg.name !== "app") {
8002
8054
  return pkg.name.startsWith("@") ? pkg.name.split("/")[1] || pkg.name : pkg.name;
8003
8055
  }
8004
8056
  } catch {}
@@ -8067,46 +8119,6 @@ class ProjectAnalyzer {
8067
8119
  return "npm";
8068
8120
  return;
8069
8121
  }
8070
- scanDirectoryStructure() {
8071
- const structure = {};
8072
- const commonDirPurposes = {
8073
- src: "Core application source code and business logic",
8074
- lib: "Shared libraries, utilities, and helper modules",
8075
- tests: "Automated unit and integration test suites",
8076
- test: "Automated test suite",
8077
- dist: "Compiled production distribution output",
8078
- build: "Compiled build artifacts",
8079
- docs: "Documentation and architectural specifications",
8080
- pkg: "Reusable public Go/Rust/JS packages",
8081
- cmd: "Main application CLI commands and entry points",
8082
- bin: "CLI executable launcher scripts and binaries",
8083
- templates: "Prompt and code generator templates",
8084
- components: "Reusable UI components",
8085
- app: "Application pages and routing handlers",
8086
- pages: "Page views and route controllers",
8087
- api: "Backend API endpoints and server routes",
8088
- public: "Static public assets and web resources",
8089
- assets: "Media assets, icons, and graphic resources",
8090
- scripts: "Build automation, CI helpers, and deployment scripts",
8091
- config: "Application configuration files",
8092
- storage: "Local databases, caches, and persistent state files"
8093
- };
8094
- try {
8095
- const entries = readdirSync6(this.cwd);
8096
- for (const entry of entries) {
8097
- if (entry.startsWith(".") || entry === "node_modules" || entry === "target")
8098
- continue;
8099
- const fullPath = join9(this.cwd, entry);
8100
- try {
8101
- if (statSync4(fullPath).isDirectory()) {
8102
- const purpose = commonDirPurposes[entry.toLowerCase()] || `Directory for ${entry} modules`;
8103
- structure[`${entry}/`] = purpose;
8104
- }
8105
- } catch {}
8106
- }
8107
- } catch {}
8108
- return structure;
8109
- }
8110
8122
  hasFileWithExtension(...exts) {
8111
8123
  try {
8112
8124
  const entries = readdirSync6(this.cwd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikaa-ai/pikaa",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "description": "PIKAA CLI - AI coding agent that runs locally in your terminal.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",