@pikaa-ai/pikaa 0.3.10 → 0.3.11

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/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  // src/cli/index.ts
5
5
  import { resolve as resolve21 } from "path";
6
- import { existsSync as existsSync19 } from "fs";
6
+ import { existsSync as existsSync21 } from "fs";
7
7
  import { createInterface } from "readline";
8
8
 
9
9
  // src/auth/store.ts
@@ -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.10",
6046
+ version: "0.3.11",
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",
@@ -7766,9 +7766,429 @@ if (false) {}
7766
7766
  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
+ // src/init/project-analyzer.ts
7770
+ import { existsSync as existsSync18, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
7771
+ import { join as join9, basename as basename2 } from "path";
7772
+
7773
+ class ProjectAnalyzer {
7774
+ cwd;
7775
+ constructor(cwd = process.cwd()) {
7776
+ this.cwd = cwd;
7777
+ }
7778
+ analyze() {
7779
+ const projectName = this.detectProjectName();
7780
+ const languages = this.detectLanguages();
7781
+ const packageManager = this.detectPackageManager();
7782
+ const frameworks = [];
7783
+ const commands = {};
7784
+ const codeConventions = [];
7785
+ let description;
7786
+ const pkgPath = join9(this.cwd, "package.json");
7787
+ if (existsSync18(pkgPath)) {
7788
+ try {
7789
+ const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
7790
+ if (pkg.description)
7791
+ description = pkg.description;
7792
+ const pm = packageManager || "npm";
7793
+ const runPrefix = pm === "bun" || pm === "yarn" || pm === "pnpm" ? `${pm} run` : "npm run";
7794
+ const testPrefix = pm === "bun" ? "bun test" : pm === "pnpm" ? "pnpm test" : pm === "yarn" ? "yarn test" : "npm test";
7795
+ if (pkg.scripts) {
7796
+ if (pkg.scripts.build)
7797
+ commands.build = `${runPrefix} build`;
7798
+ if (pkg.scripts.test)
7799
+ commands.test = pkg.scripts.test === "bun test" ? "bun test" : testPrefix;
7800
+ if (pkg.scripts.typecheck)
7801
+ commands.typecheck = `${runPrefix} typecheck`;
7802
+ else if (pkg.scripts.check)
7803
+ commands.typecheck = `${runPrefix} check`;
7804
+ if (pkg.scripts.lint)
7805
+ 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
+ if (pkg.scripts.format)
7811
+ commands.format = `${runPrefix} format`;
7812
+ }
7813
+ const allDeps = {
7814
+ ...pkg.dependencies || {},
7815
+ ...pkg.devDependencies || {}
7816
+ };
7817
+ if (allDeps.next)
7818
+ frameworks.push("Next.js");
7819
+ if (allDeps.react)
7820
+ frameworks.push("React");
7821
+ if (allDeps.vue)
7822
+ frameworks.push("Vue.js");
7823
+ if (allDeps.svelte || allDeps["@sveltejs/kit"])
7824
+ frameworks.push("Svelte");
7825
+ if (allDeps.astro)
7826
+ frameworks.push("Astro");
7827
+ if (allDeps.express)
7828
+ frameworks.push("Express");
7829
+ if (allDeps.hono)
7830
+ frameworks.push("Hono");
7831
+ if (allDeps.fastify)
7832
+ frameworks.push("Fastify");
7833
+ if (allDeps["@nestjs/core"])
7834
+ frameworks.push("NestJS");
7835
+ if (allDeps.tailwindcss)
7836
+ frameworks.push("TailwindCSS");
7837
+ if (allDeps.vitest)
7838
+ frameworks.push("Vitest");
7839
+ if (allDeps.jest)
7840
+ frameworks.push("Jest");
7841
+ if (allDeps.playwright || allDeps["@playwright/test"])
7842
+ frameworks.push("Playwright");
7843
+ if (pkg.type === "module") {
7844
+ codeConventions.push('ES Modules enabled (`"type": "module"`)');
7845
+ } else {
7846
+ codeConventions.push("CommonJS module format");
7847
+ }
7848
+ } catch {}
7849
+ }
7850
+ const tsconfigPath = join9(this.cwd, "tsconfig.json");
7851
+ if (existsSync18(tsconfigPath)) {
7852
+ try {
7853
+ const tsconfig = JSON.parse(readFileSync13(tsconfigPath, "utf8"));
7854
+ if (tsconfig.compilerOptions?.strict) {
7855
+ codeConventions.push("TypeScript Strict Mode enabled");
7856
+ }
7857
+ if (!commands.typecheck) {
7858
+ commands.typecheck = "tsc --noEmit";
7859
+ }
7860
+ } catch {}
7861
+ }
7862
+ const cargoPath = join9(this.cwd, "Cargo.toml");
7863
+ if (existsSync18(cargoPath)) {
7864
+ try {
7865
+ const content = readFileSync13(cargoPath, "utf8");
7866
+ commands.build = commands.build || "cargo build";
7867
+ commands.test = commands.test || "cargo test";
7868
+ 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");
7879
+ } catch {}
7880
+ }
7881
+ const goModPath = join9(this.cwd, "go.mod");
7882
+ if (existsSync18(goModPath)) {
7883
+ try {
7884
+ const content = readFileSync13(goModPath, "utf8");
7885
+ commands.build = commands.build || "go build ./...";
7886
+ commands.test = commands.test || "go test ./...";
7887
+ 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
+ }
7893
+ } catch {}
7894
+ }
7895
+ const pyprojectPath = join9(this.cwd, "pyproject.toml");
7896
+ const requirementsPath = join9(this.cwd, "requirements.txt");
7897
+ if (existsSync18(pyprojectPath) || existsSync18(requirementsPath)) {
7898
+ commands.test = commands.test || "pytest";
7899
+ commands.lint = commands.lint || "ruff check .";
7900
+ commands.format = commands.format || "black .";
7901
+ if (existsSync18(join9(this.cwd, "uv.lock"))) {
7902
+ codeConventions.push("uv package & project manager");
7903
+ commands.test = "uv run pytest";
7904
+ } else if (existsSync18(join9(this.cwd, "poetry.lock"))) {
7905
+ codeConventions.push("Poetry dependency manager");
7906
+ commands.test = "poetry run pytest";
7907
+ }
7908
+ }
7909
+ const directoryStructure = this.scanDirectoryStructure();
7910
+ const instructionFiles = ["AGENTS.md", "CLAUDE.md", ".agents.md", "AGENTS.override.md"];
7911
+ let hasExistingInstructions = false;
7912
+ let existingInstructionFile;
7913
+ for (const f of instructionFiles) {
7914
+ if (existsSync18(join9(this.cwd, f))) {
7915
+ hasExistingInstructions = true;
7916
+ existingInstructionFile = f;
7917
+ break;
7918
+ }
7919
+ }
7920
+ return {
7921
+ projectName,
7922
+ description,
7923
+ languages,
7924
+ packageManager,
7925
+ frameworks,
7926
+ commands,
7927
+ directoryStructure,
7928
+ codeConventions,
7929
+ hasExistingInstructions,
7930
+ existingInstructionFile
7931
+ };
7932
+ }
7933
+ generateAgentsMarkdown(analysis) {
7934
+ const lines = [];
7935
+ lines.push(`# ${analysis.projectName}`);
7936
+ lines.push("");
7937
+ if (analysis.description) {
7938
+ lines.push(`> ${analysis.description}`);
7939
+ lines.push("");
7940
+ }
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");
7954
+ lines.push("");
7955
+ if (Object.keys(analysis.commands).length > 0) {
7956
+ if (analysis.commands.build)
7957
+ lines.push(`- **Build**: \`${analysis.commands.build}\``);
7958
+ if (analysis.commands.test)
7959
+ lines.push(`- **Test**: \`${analysis.commands.test}\``);
7960
+ if (analysis.commands.typecheck)
7961
+ lines.push(`- **Typecheck**: \`${analysis.commands.typecheck}\``);
7962
+ if (analysis.commands.lint)
7963
+ lines.push(`- **Lint**: \`${analysis.commands.lint}\``);
7964
+ if (analysis.commands.dev)
7965
+ lines.push(`- **Dev / Run**: \`${analysis.commands.dev}\``);
7966
+ if (analysis.commands.format)
7967
+ lines.push(`- **Format**: \`${analysis.commands.format}\``);
7968
+ } else {
7969
+ lines.push("- *No standard build/test commands detected.*");
7970
+ }
7971
+ lines.push("");
7972
+ lines.push("## Architecture & Directory Structure");
7973
+ 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");
7980
+ }
7981
+ lines.push("");
7982
+ lines.push("## Code Style & Guidelines");
7983
+ lines.push("");
7984
+ if (analysis.codeConventions.length > 0) {
7985
+ for (const conv of analysis.codeConventions) {
7986
+ lines.push(`- ${conv}`);
7987
+ }
7988
+ }
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.");
7992
+ lines.push("");
7993
+ return lines.join(`
7994
+ `);
7995
+ }
7996
+ detectProjectName() {
7997
+ const pkgPath = join9(this.cwd, "package.json");
7998
+ if (existsSync18(pkgPath)) {
7999
+ try {
8000
+ const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
8001
+ if (pkg.name) {
8002
+ return pkg.name.startsWith("@") ? pkg.name.split("/")[1] || pkg.name : pkg.name;
8003
+ }
8004
+ } catch {}
8005
+ }
8006
+ const cargoPath = join9(this.cwd, "Cargo.toml");
8007
+ if (existsSync18(cargoPath)) {
8008
+ try {
8009
+ const match = readFileSync13(cargoPath, "utf8").match(/name\s*=\s*"([^"]+)"/);
8010
+ if (match?.[1])
8011
+ return match[1];
8012
+ } catch {}
8013
+ }
8014
+ const goModPath = join9(this.cwd, "go.mod");
8015
+ if (existsSync18(goModPath)) {
8016
+ try {
8017
+ const match = readFileSync13(goModPath, "utf8").match(/module\s+([^\s]+)/);
8018
+ if (match?.[1])
8019
+ return basename2(match[1]);
8020
+ } catch {}
8021
+ }
8022
+ return basename2(this.cwd);
8023
+ }
8024
+ detectLanguages() {
8025
+ const langs = new Set;
8026
+ if (existsSync18(join9(this.cwd, "tsconfig.json")) || this.hasFileWithExtension(".ts", ".tsx")) {
8027
+ langs.add("TypeScript");
8028
+ }
8029
+ if (existsSync18(join9(this.cwd, "package.json")) || this.hasFileWithExtension(".js", ".jsx", ".mjs")) {
8030
+ langs.add("JavaScript");
8031
+ }
8032
+ if (existsSync18(join9(this.cwd, "Cargo.toml")) || this.hasFileWithExtension(".rs")) {
8033
+ langs.add("Rust");
8034
+ }
8035
+ if (existsSync18(join9(this.cwd, "go.mod")) || this.hasFileWithExtension(".go")) {
8036
+ langs.add("Go");
8037
+ }
8038
+ if (existsSync18(join9(this.cwd, "pyproject.toml")) || existsSync18(join9(this.cwd, "requirements.txt")) || this.hasFileWithExtension(".py")) {
8039
+ langs.add("Python");
8040
+ }
8041
+ if (existsSync18(join9(this.cwd, "pom.xml")) || existsSync18(join9(this.cwd, "build.gradle")) || this.hasFileWithExtension(".java")) {
8042
+ langs.add("Java");
8043
+ }
8044
+ if (existsSync18(join9(this.cwd, "CMakeLists.txt")) || this.hasFileWithExtension(".cpp", ".c", ".h", ".hpp")) {
8045
+ langs.add("C/C++");
8046
+ }
8047
+ return Array.from(langs);
8048
+ }
8049
+ detectPackageManager() {
8050
+ if (existsSync18(join9(this.cwd, "bun.lockb")) || existsSync18(join9(this.cwd, "bun.lock")))
8051
+ return "bun";
8052
+ if (existsSync18(join9(this.cwd, "pnpm-lock.yaml")))
8053
+ return "pnpm";
8054
+ if (existsSync18(join9(this.cwd, "yarn.lock")))
8055
+ return "yarn";
8056
+ if (existsSync18(join9(this.cwd, "package-lock.json")))
8057
+ return "npm";
8058
+ if (existsSync18(join9(this.cwd, "Cargo.lock")) || existsSync18(join9(this.cwd, "Cargo.toml")))
8059
+ return "cargo";
8060
+ if (existsSync18(join9(this.cwd, "uv.lock")))
8061
+ return "uv";
8062
+ if (existsSync18(join9(this.cwd, "poetry.lock")))
8063
+ return "poetry";
8064
+ if (existsSync18(join9(this.cwd, "go.sum")) || existsSync18(join9(this.cwd, "go.mod")))
8065
+ return "go";
8066
+ if (existsSync18(join9(this.cwd, "package.json")))
8067
+ return "npm";
8068
+ return;
8069
+ }
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
+ hasFileWithExtension(...exts) {
8111
+ try {
8112
+ const entries = readdirSync6(this.cwd);
8113
+ return entries.some((e) => exts.some((ext) => e.endsWith(ext)));
8114
+ } catch {
8115
+ return false;
8116
+ }
8117
+ }
8118
+ }
8119
+ // src/init/init-command.ts
8120
+ import { existsSync as existsSync19, writeFileSync as writeFileSync7 } from "fs";
8121
+ import { join as join10 } from "path";
8122
+ function runProjectInit(options = {}) {
8123
+ const cwd = options.cwd || process.cwd();
8124
+ const filename = options.filename || "AGENTS.md";
8125
+ const targetPath = join10(cwd, filename);
8126
+ const analyzer = new ProjectAnalyzer(cwd);
8127
+ const analysis = analyzer.analyze();
8128
+ const content = analyzer.generateAgentsMarkdown(analysis);
8129
+ const alreadyExists = existsSync19(targetPath);
8130
+ writeFileSync7(targetPath, content, "utf8");
8131
+ return {
8132
+ success: true,
8133
+ filePath: targetPath,
8134
+ analysis,
8135
+ content,
8136
+ overwritten: alreadyExists
8137
+ };
8138
+ }
8139
+ function printInitSummary(result) {
8140
+ const BOLD2 = "\x1B[1m";
8141
+ const GREEN = "\x1B[38;2;120;220;140m";
8142
+ const BRAND = "\x1B[38;2;217;119;87m";
8143
+ const CYAN = "\x1B[38;2;125;207;255m";
8144
+ const GRAY2 = "\x1B[38;2;148;148;148m";
8145
+ const WHITE2 = "\x1B[38;2;240;240;245m";
8146
+ const RESET2 = "\x1B[0m";
8147
+ const { analysis, filePath, overwritten } = result;
8148
+ console.log("");
8149
+ console.log(` ${GREEN}\u2713${RESET2} ${BOLD2}${WHITE2}${overwritten ? "Updated" : "Created"} Project Instructions Document${RESET2}`);
8150
+ console.log(` ${GRAY2}Path: ${CYAN}${filePath}${RESET2}`);
8151
+ console.log("");
8152
+ console.log(` ${BRAND}\u250C\u2500 ${BOLD2}Project Overview${RESET2} ${BRAND}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${RESET2}`);
8153
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Project:${RESET2} ${WHITE2}${analysis.projectName}${RESET2}`);
8154
+ if (analysis.languages.length > 0) {
8155
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Languages:${RESET2} ${analysis.languages.join(", ")}`);
8156
+ }
8157
+ if (analysis.packageManager) {
8158
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Package Manager:${RESET2} ${analysis.packageManager}`);
8159
+ }
8160
+ if (analysis.frameworks.length > 0) {
8161
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Frameworks:${RESET2} ${analysis.frameworks.join(", ")}`);
8162
+ }
8163
+ console.log(` ${BRAND}\u2502${RESET2}`);
8164
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Detected Commands:${RESET2}`);
8165
+ if (analysis.commands.build) {
8166
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Build: ${CYAN}${analysis.commands.build}${RESET2}`);
8167
+ }
8168
+ if (analysis.commands.test) {
8169
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Test: ${GREEN}${analysis.commands.test}${RESET2}`);
8170
+ }
8171
+ if (analysis.commands.typecheck) {
8172
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Typecheck: ${CYAN}${analysis.commands.typecheck}${RESET2}`);
8173
+ }
8174
+ if (analysis.commands.lint) {
8175
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Lint: ${CYAN}${analysis.commands.lint}${RESET2}`);
8176
+ }
8177
+ if (analysis.commands.dev) {
8178
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Dev: ${CYAN}${analysis.commands.dev}${RESET2}`);
8179
+ }
8180
+ if (Object.keys(analysis.commands).length === 0) {
8181
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 ${GRAY2}(No standard commands detected)${RESET2}`);
8182
+ }
8183
+ console.log(` ${BRAND}\u2502${RESET2}`);
8184
+ console.log(` ${BRAND}\u2502${RESET2} ${GRAY2}AI agents will now automatically load AGENTS.md on every session.${RESET2}`);
8185
+ console.log(` ${BRAND}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${RESET2}`);
8186
+ console.log("");
8187
+ }
7769
8188
  // src/cli/commands.ts
7770
8189
  var AVAILABLE_SLASH_COMMANDS = [
7771
8190
  { name: "/help", description: "Show command list and help menu" },
8191
+ { name: "/init", description: "Initialize or update AGENTS.md project instructions" },
7772
8192
  { name: "/stats", description: "Display session runtime, turn stats & sub-agent status" },
7773
8193
  { name: "/model", description: "Select or switch active AI model" },
7774
8194
  { name: "/reasoning", description: "Toggle internal reasoning chain visibility" },
@@ -7861,6 +8281,10 @@ async function handleSlashCommand(input, ctx) {
7861
8281
  \x1B[38;2;95;175;175m\u23F8 Switched to Plan Mode (read-only planning, mutations blocked)\x1B[0m
7862
8282
  `);
7863
8283
  return true;
8284
+ case "/init":
8285
+ const initResult = runProjectInit({ cwd: ctx.session.cwd });
8286
+ printInitSummary(initResult);
8287
+ return true;
7864
8288
  case "/agents":
7865
8289
  printAgents(ctx);
7866
8290
  return true;
@@ -9126,9 +9550,9 @@ class MarkdownHighlighter {
9126
9550
  }
9127
9551
 
9128
9552
  // src/cli/update-checker.ts
9129
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "fs";
9553
+ import { existsSync as existsSync20, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
9130
9554
  import { homedir as homedir9 } from "os";
9131
- import { join as join9 } from "path";
9555
+ import { join as join11 } from "path";
9132
9556
  var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
9133
9557
  function parseSemver(v) {
9134
9558
  const clean = v.replace(/^v/, "").trim();
@@ -9149,8 +9573,8 @@ function isNewerVersion(current, remote) {
9149
9573
  return remPatch > curPatch;
9150
9574
  }
9151
9575
  function getUpdateCachePath() {
9152
- const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join9(homedir9(), ".pikaa");
9153
- return join9(baseDir, "update-cache.json");
9576
+ const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join11(homedir9(), ".pikaa");
9577
+ return join11(baseDir, "update-cache.json");
9154
9578
  }
9155
9579
  async function fetchLatestNpmVersion(packageName, timeoutMs = 1500) {
9156
9580
  const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
@@ -9183,9 +9607,9 @@ async function checkForUpdates(options = {}) {
9183
9607
  const cachePath = options.cachePath || getUpdateCachePath();
9184
9608
  const now = Date.now();
9185
9609
  let cached = null;
9186
- if (!options.force && existsSync18(cachePath)) {
9610
+ if (!options.force && existsSync20(cachePath)) {
9187
9611
  try {
9188
- const raw = JSON.parse(readFileSync13(cachePath, "utf8"));
9612
+ const raw = JSON.parse(readFileSync14(cachePath, "utf8"));
9189
9613
  if (raw && typeof raw.lastChecked === "number" && typeof raw.latestVersion === "string") {
9190
9614
  cached = raw;
9191
9615
  if (now - cached.lastChecked < CHECK_INTERVAL_MS) {
@@ -9213,8 +9637,8 @@ async function checkForUpdates(options = {}) {
9213
9637
  return null;
9214
9638
  }
9215
9639
  try {
9216
- const parentDir = join9(cachePath, "..");
9217
- if (!existsSync18(parentDir)) {
9640
+ const parentDir = join11(cachePath, "..");
9641
+ if (!existsSync20(parentDir)) {
9218
9642
  mkdirSync10(parentDir, { recursive: true });
9219
9643
  }
9220
9644
  const cacheData = {
@@ -9222,7 +9646,7 @@ async function checkForUpdates(options = {}) {
9222
9646
  latestVersion,
9223
9647
  packageName
9224
9648
  };
9225
- writeFileSync7(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
9649
+ writeFileSync8(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
9226
9650
  } catch {}
9227
9651
  const updateAvailable = isNewerVersion(currentVersion, latestVersion);
9228
9652
  return updateAvailable ? {
@@ -9589,6 +10013,10 @@ async function main() {
9589
10013
  } else if (arg === "worktrees" || arg === "worktree") {
9590
10014
  await printWorktreesList(worktreeManager, cwd);
9591
10015
  process.exit(0);
10016
+ } else if (arg === "init") {
10017
+ const initResult = runProjectInit({ cwd });
10018
+ printInitSummary(initResult);
10019
+ process.exit(0);
9592
10020
  } else if (arg === "--resume" || arg === "-R" || arg === "resume") {
9593
10021
  resumeThreadId = args[++i];
9594
10022
  } else if (arg === "--model" || arg === "-m") {
@@ -9630,7 +10058,7 @@ async function main() {
9630
10058
  resolve21(cwd, "mcp_config.json")
9631
10059
  ].filter(Boolean);
9632
10060
  for (const cfg of candidateConfigs) {
9633
- if (existsSync19(cfg)) {
10061
+ if (existsSync21(cfg)) {
9634
10062
  try {
9635
10063
  await mcpManager.loadConfigFile(cfg);
9636
10064
  mcpManager.registerToolsIntoRouter(tools4);
@@ -9888,6 +10316,7 @@ ${style.bold("USAGE:")}
9888
10316
  groupy skills # List available domain skills
9889
10317
  groupy memories # View learned user preferences
9890
10318
  groupy worktrees # List active isolated Git Worktrees
10319
+ groupy init # Initialize or update AGENTS.md project instructions
9891
10320
 
9892
10321
  ${style.bold("OPTIONS:")}
9893
10322
  -R, --resume <id> Resume an existing session from SQLite storage
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikaa-ai/pikaa",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
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",
@@ -47,6 +47,10 @@ You are Groupy, an expert autonomous AI coding assistant. You are running as a c
47
47
 
48
48
  ## Codebase Discovery & Execution Strategy
49
49
 
50
+ 0. **Project Instructions Precedence (`AGENTS.md` / `CLAUDE.md`)**:
51
+ - If `AGENTS.md`, `CLAUDE.md`, or `.agents.md` is present in the workspace, its instructions take immediate precedence.
52
+ - Always prioritize and follow the development commands (build, test, lint), architectural constraints, and code conventions defined in `AGENTS.md` before executing any commands.
53
+
50
54
  1. **Broad Exploration ("pelajari project ini / repo ini tentang apa")**:
51
55
  - Inspect ONLY root configs (`package.json`, `Cargo.toml`, `go.mod`, `pyproject.toml`, etc.), `README.md`, and top-level directory tree.
52
56
  - Deliver a concise Architecture Overview (Tech stack, folder hierarchy, main entry points).