@pikaa-ai/pikaa 0.3.10 → 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.
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.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",
@@ -7766,9 +7766,441 @@ 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 } 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 readmeInfo = this.extractReadmeMetadata();
7780
+ const projectName = readmeInfo.title || this.detectProjectName();
7781
+ const languages = this.detectLanguages();
7782
+ const packageManager = this.detectPackageManager();
7783
+ const frameworks = [];
7784
+ const infrastructure = [];
7785
+ const commands = {};
7786
+ const architectureNotes = [];
7787
+ const codeConventions = [];
7788
+ let description = readmeInfo.description;
7789
+ const pkgPath = join9(this.cwd, "package.json");
7790
+ if (existsSync18(pkgPath)) {
7791
+ try {
7792
+ const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
7793
+ if (!description && pkg.description)
7794
+ description = pkg.description;
7795
+ const pm = packageManager || "npm";
7796
+ const runPrefix = pm === "bun" || pm === "yarn" || pm === "pnpm" ? `${pm} run` : "npm run";
7797
+ const testPrefix = pm === "bun" ? "bun test" : pm === "pnpm" ? "pnpm test" : pm === "yarn" ? "yarn test" : "npm test";
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`;
7803
+ if (pkg.scripts.build)
7804
+ commands.build = `${runPrefix} build`;
7805
+ if (pkg.scripts.test)
7806
+ commands.test = pkg.scripts.test === "bun test" ? "bun test" : testPrefix;
7807
+ if (pkg.scripts.typecheck)
7808
+ commands.typecheck = `${runPrefix} typecheck`;
7809
+ else if (pkg.scripts.check)
7810
+ commands.typecheck = `${runPrefix} check`;
7811
+ if (pkg.scripts.lint)
7812
+ commands.lint = `${runPrefix} lint`;
7813
+ if (pkg.scripts.format)
7814
+ commands.format = `${runPrefix} format`;
7815
+ }
7816
+ const allDeps = {
7817
+ ...pkg.dependencies || {},
7818
+ ...pkg.devDependencies || {}
7819
+ };
7820
+ if (allDeps.next)
7821
+ frameworks.push("Next.js");
7822
+ if (allDeps.react)
7823
+ frameworks.push("React");
7824
+ if (allDeps.vue)
7825
+ frameworks.push("Vue.js");
7826
+ if (allDeps.svelte || allDeps["@sveltejs/kit"])
7827
+ frameworks.push("Svelte");
7828
+ if (allDeps.astro)
7829
+ frameworks.push("Astro");
7830
+ if (allDeps.vite)
7831
+ frameworks.push("Vite");
7832
+ if (allDeps.express)
7833
+ frameworks.push("Express");
7834
+ if (allDeps.hono)
7835
+ frameworks.push("Hono");
7836
+ if (allDeps.fastify)
7837
+ frameworks.push("Fastify");
7838
+ if (allDeps["@nestjs/core"])
7839
+ frameworks.push("NestJS");
7840
+ if (allDeps.tailwindcss)
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");
7852
+ if (allDeps.vitest)
7853
+ frameworks.push("Vitest");
7854
+ if (allDeps.jest)
7855
+ frameworks.push("Jest");
7856
+ if (allDeps.playwright || allDeps["@playwright/test"])
7857
+ frameworks.push("Playwright");
7858
+ if (pkg.type === "module") {
7859
+ codeConventions.push("Use ES modules (`import/export`), not CommonJS (`require`).");
7860
+ }
7861
+ } catch {}
7862
+ }
7863
+ const tsconfigPath = join9(this.cwd, "tsconfig.json");
7864
+ if (existsSync18(tsconfigPath)) {
7865
+ try {
7866
+ const tsconfig = JSON.parse(readFileSync13(tsconfigPath, "utf8"));
7867
+ if (tsconfig.compilerOptions?.strict) {
7868
+ codeConventions.push("TypeScript strict mode enabled.");
7869
+ }
7870
+ if (!commands.typecheck) {
7871
+ commands.typecheck = "tsc --noEmit";
7872
+ }
7873
+ } catch {}
7874
+ }
7875
+ const cargoPath = join9(this.cwd, "Cargo.toml");
7876
+ if (existsSync18(cargoPath)) {
7877
+ try {
7878
+ commands.dev = commands.dev || "cargo run";
7879
+ commands.build = commands.build || "cargo build";
7880
+ commands.test = commands.test || "cargo test";
7881
+ commands.lint = commands.lint || "cargo clippy";
7882
+ frameworks.push("Rust Cargo");
7883
+ } catch {}
7884
+ }
7885
+ const goModPath = join9(this.cwd, "go.mod");
7886
+ if (existsSync18(goModPath)) {
7887
+ try {
7888
+ commands.dev = commands.dev || "go run .";
7889
+ commands.build = commands.build || "go build ./...";
7890
+ commands.test = commands.test || "go test ./...";
7891
+ commands.lint = commands.lint || "golangci-lint run";
7892
+ frameworks.push("Go Modules");
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
+ if (existsSync18(join9(this.cwd, "uv.lock"))) {
7901
+ frameworks.push("uv");
7902
+ commands.test = "uv run pytest";
7903
+ } else if (existsSync18(join9(this.cwd, "poetry.lock"))) {
7904
+ frameworks.push("Poetry");
7905
+ commands.test = "poetry run pytest";
7906
+ }
7907
+ }
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
+ }
7938
+ const instructionFiles = ["AGENTS.md", "CLAUDE.md", ".agents.md", "AGENTS.override.md"];
7939
+ let hasExistingInstructions = false;
7940
+ let existingInstructionFile;
7941
+ for (const f of instructionFiles) {
7942
+ if (existsSync18(join9(this.cwd, f))) {
7943
+ hasExistingInstructions = true;
7944
+ existingInstructionFile = f;
7945
+ break;
7946
+ }
7947
+ }
7948
+ return {
7949
+ projectName,
7950
+ description,
7951
+ languages,
7952
+ packageManager,
7953
+ frameworks,
7954
+ infrastructure,
7955
+ commands,
7956
+ architectureNotes,
7957
+ codeConventions,
7958
+ hasExistingInstructions,
7959
+ existingInstructionFile
7960
+ };
7961
+ }
7962
+ generateAgentsMarkdown(analysis) {
7963
+ const lines = [];
7964
+ lines.push(`# ${analysis.projectName}`);
7965
+ lines.push("");
7966
+ if (analysis.description) {
7967
+ lines.push(`> ${analysis.description}`);
7968
+ lines.push("");
7969
+ }
7970
+ lines.push("## Commands");
7971
+ lines.push("");
7972
+ if (Object.keys(analysis.commands).length > 0) {
7973
+ if (analysis.commands.dev)
7974
+ lines.push(`- **Dev Server**: \`${analysis.commands.dev}\``);
7975
+ if (analysis.commands.build)
7976
+ lines.push(`- **Build**: \`${analysis.commands.build}\``);
7977
+ if (analysis.commands.test)
7978
+ lines.push(`- **Test**: \`${analysis.commands.test}\``);
7979
+ if (analysis.commands.typecheck)
7980
+ lines.push(`- **Typecheck**: \`${analysis.commands.typecheck}\``);
7981
+ if (analysis.commands.lint)
7982
+ lines.push(`- **Lint**: \`${analysis.commands.lint}\``);
7983
+ if (analysis.commands.format)
7984
+ lines.push(`- **Format**: \`${analysis.commands.format}\``);
7985
+ if (analysis.commands.dockerBuild)
7986
+ lines.push(`- **Docker Build**: \`${analysis.commands.dockerBuild}\``);
7987
+ } else {
7988
+ lines.push("- *No standard build/test commands detected.*");
7989
+ }
7990
+ lines.push("");
7991
+ lines.push("## Architecture & Stack");
7992
+ lines.push("");
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}`);
8005
+ }
8006
+ lines.push("");
8007
+ lines.push("## Workflow & Code Guidelines");
8008
+ lines.push("");
8009
+ if (analysis.codeConventions.length > 0) {
8010
+ for (const conv of analysis.codeConventions) {
8011
+ lines.push(`- ${conv}`);
8012
+ }
8013
+ }
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.");
8016
+ lines.push("");
8017
+ return lines.join(`
8018
+ `);
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
+ }
8048
+ detectProjectName() {
8049
+ const pkgPath = join9(this.cwd, "package.json");
8050
+ if (existsSync18(pkgPath)) {
8051
+ try {
8052
+ const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
8053
+ if (pkg.name && pkg.name !== "frontend" && pkg.name !== "backend" && pkg.name !== "app") {
8054
+ return pkg.name.startsWith("@") ? pkg.name.split("/")[1] || pkg.name : pkg.name;
8055
+ }
8056
+ } catch {}
8057
+ }
8058
+ const cargoPath = join9(this.cwd, "Cargo.toml");
8059
+ if (existsSync18(cargoPath)) {
8060
+ try {
8061
+ const match = readFileSync13(cargoPath, "utf8").match(/name\s*=\s*"([^"]+)"/);
8062
+ if (match?.[1])
8063
+ return match[1];
8064
+ } catch {}
8065
+ }
8066
+ const goModPath = join9(this.cwd, "go.mod");
8067
+ if (existsSync18(goModPath)) {
8068
+ try {
8069
+ const match = readFileSync13(goModPath, "utf8").match(/module\s+([^\s]+)/);
8070
+ if (match?.[1])
8071
+ return basename2(match[1]);
8072
+ } catch {}
8073
+ }
8074
+ return basename2(this.cwd);
8075
+ }
8076
+ detectLanguages() {
8077
+ const langs = new Set;
8078
+ if (existsSync18(join9(this.cwd, "tsconfig.json")) || this.hasFileWithExtension(".ts", ".tsx")) {
8079
+ langs.add("TypeScript");
8080
+ }
8081
+ if (existsSync18(join9(this.cwd, "package.json")) || this.hasFileWithExtension(".js", ".jsx", ".mjs")) {
8082
+ langs.add("JavaScript");
8083
+ }
8084
+ if (existsSync18(join9(this.cwd, "Cargo.toml")) || this.hasFileWithExtension(".rs")) {
8085
+ langs.add("Rust");
8086
+ }
8087
+ if (existsSync18(join9(this.cwd, "go.mod")) || this.hasFileWithExtension(".go")) {
8088
+ langs.add("Go");
8089
+ }
8090
+ if (existsSync18(join9(this.cwd, "pyproject.toml")) || existsSync18(join9(this.cwd, "requirements.txt")) || this.hasFileWithExtension(".py")) {
8091
+ langs.add("Python");
8092
+ }
8093
+ if (existsSync18(join9(this.cwd, "pom.xml")) || existsSync18(join9(this.cwd, "build.gradle")) || this.hasFileWithExtension(".java")) {
8094
+ langs.add("Java");
8095
+ }
8096
+ if (existsSync18(join9(this.cwd, "CMakeLists.txt")) || this.hasFileWithExtension(".cpp", ".c", ".h", ".hpp")) {
8097
+ langs.add("C/C++");
8098
+ }
8099
+ return Array.from(langs);
8100
+ }
8101
+ detectPackageManager() {
8102
+ if (existsSync18(join9(this.cwd, "bun.lockb")) || existsSync18(join9(this.cwd, "bun.lock")))
8103
+ return "bun";
8104
+ if (existsSync18(join9(this.cwd, "pnpm-lock.yaml")))
8105
+ return "pnpm";
8106
+ if (existsSync18(join9(this.cwd, "yarn.lock")))
8107
+ return "yarn";
8108
+ if (existsSync18(join9(this.cwd, "package-lock.json")))
8109
+ return "npm";
8110
+ if (existsSync18(join9(this.cwd, "Cargo.lock")) || existsSync18(join9(this.cwd, "Cargo.toml")))
8111
+ return "cargo";
8112
+ if (existsSync18(join9(this.cwd, "uv.lock")))
8113
+ return "uv";
8114
+ if (existsSync18(join9(this.cwd, "poetry.lock")))
8115
+ return "poetry";
8116
+ if (existsSync18(join9(this.cwd, "go.sum")) || existsSync18(join9(this.cwd, "go.mod")))
8117
+ return "go";
8118
+ if (existsSync18(join9(this.cwd, "package.json")))
8119
+ return "npm";
8120
+ return;
8121
+ }
8122
+ hasFileWithExtension(...exts) {
8123
+ try {
8124
+ const entries = readdirSync6(this.cwd);
8125
+ return entries.some((e) => exts.some((ext) => e.endsWith(ext)));
8126
+ } catch {
8127
+ return false;
8128
+ }
8129
+ }
8130
+ }
8131
+ // src/init/init-command.ts
8132
+ import { existsSync as existsSync19, writeFileSync as writeFileSync7 } from "fs";
8133
+ import { join as join10 } from "path";
8134
+ function runProjectInit(options = {}) {
8135
+ const cwd = options.cwd || process.cwd();
8136
+ const filename = options.filename || "AGENTS.md";
8137
+ const targetPath = join10(cwd, filename);
8138
+ const analyzer = new ProjectAnalyzer(cwd);
8139
+ const analysis = analyzer.analyze();
8140
+ const content = analyzer.generateAgentsMarkdown(analysis);
8141
+ const alreadyExists = existsSync19(targetPath);
8142
+ writeFileSync7(targetPath, content, "utf8");
8143
+ return {
8144
+ success: true,
8145
+ filePath: targetPath,
8146
+ analysis,
8147
+ content,
8148
+ overwritten: alreadyExists
8149
+ };
8150
+ }
8151
+ function printInitSummary(result) {
8152
+ const BOLD2 = "\x1B[1m";
8153
+ const GREEN = "\x1B[38;2;120;220;140m";
8154
+ const BRAND = "\x1B[38;2;217;119;87m";
8155
+ const CYAN = "\x1B[38;2;125;207;255m";
8156
+ const GRAY2 = "\x1B[38;2;148;148;148m";
8157
+ const WHITE2 = "\x1B[38;2;240;240;245m";
8158
+ const RESET2 = "\x1B[0m";
8159
+ const { analysis, filePath, overwritten } = result;
8160
+ console.log("");
8161
+ console.log(` ${GREEN}\u2713${RESET2} ${BOLD2}${WHITE2}${overwritten ? "Updated" : "Created"} Project Instructions Document${RESET2}`);
8162
+ console.log(` ${GRAY2}Path: ${CYAN}${filePath}${RESET2}`);
8163
+ console.log("");
8164
+ 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}`);
8165
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Project:${RESET2} ${WHITE2}${analysis.projectName}${RESET2}`);
8166
+ if (analysis.languages.length > 0) {
8167
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Languages:${RESET2} ${analysis.languages.join(", ")}`);
8168
+ }
8169
+ if (analysis.packageManager) {
8170
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Package Manager:${RESET2} ${analysis.packageManager}`);
8171
+ }
8172
+ if (analysis.frameworks.length > 0) {
8173
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Frameworks:${RESET2} ${analysis.frameworks.join(", ")}`);
8174
+ }
8175
+ console.log(` ${BRAND}\u2502${RESET2}`);
8176
+ console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Detected Commands:${RESET2}`);
8177
+ if (analysis.commands.build) {
8178
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Build: ${CYAN}${analysis.commands.build}${RESET2}`);
8179
+ }
8180
+ if (analysis.commands.test) {
8181
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Test: ${GREEN}${analysis.commands.test}${RESET2}`);
8182
+ }
8183
+ if (analysis.commands.typecheck) {
8184
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Typecheck: ${CYAN}${analysis.commands.typecheck}${RESET2}`);
8185
+ }
8186
+ if (analysis.commands.lint) {
8187
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Lint: ${CYAN}${analysis.commands.lint}${RESET2}`);
8188
+ }
8189
+ if (analysis.commands.dev) {
8190
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 Dev: ${CYAN}${analysis.commands.dev}${RESET2}`);
8191
+ }
8192
+ if (Object.keys(analysis.commands).length === 0) {
8193
+ console.log(` ${BRAND}\u2502${RESET2} \u2022 ${GRAY2}(No standard commands detected)${RESET2}`);
8194
+ }
8195
+ console.log(` ${BRAND}\u2502${RESET2}`);
8196
+ console.log(` ${BRAND}\u2502${RESET2} ${GRAY2}AI agents will now automatically load AGENTS.md on every session.${RESET2}`);
8197
+ 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}`);
8198
+ console.log("");
8199
+ }
7769
8200
  // src/cli/commands.ts
7770
8201
  var AVAILABLE_SLASH_COMMANDS = [
7771
8202
  { name: "/help", description: "Show command list and help menu" },
8203
+ { name: "/init", description: "Initialize or update AGENTS.md project instructions" },
7772
8204
  { name: "/stats", description: "Display session runtime, turn stats & sub-agent status" },
7773
8205
  { name: "/model", description: "Select or switch active AI model" },
7774
8206
  { name: "/reasoning", description: "Toggle internal reasoning chain visibility" },
@@ -7861,6 +8293,10 @@ async function handleSlashCommand(input, ctx) {
7861
8293
  \x1B[38;2;95;175;175m\u23F8 Switched to Plan Mode (read-only planning, mutations blocked)\x1B[0m
7862
8294
  `);
7863
8295
  return true;
8296
+ case "/init":
8297
+ const initResult = runProjectInit({ cwd: ctx.session.cwd });
8298
+ printInitSummary(initResult);
8299
+ return true;
7864
8300
  case "/agents":
7865
8301
  printAgents(ctx);
7866
8302
  return true;
@@ -9126,9 +9562,9 @@ class MarkdownHighlighter {
9126
9562
  }
9127
9563
 
9128
9564
  // src/cli/update-checker.ts
9129
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "fs";
9565
+ import { existsSync as existsSync20, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
9130
9566
  import { homedir as homedir9 } from "os";
9131
- import { join as join9 } from "path";
9567
+ import { join as join11 } from "path";
9132
9568
  var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
9133
9569
  function parseSemver(v) {
9134
9570
  const clean = v.replace(/^v/, "").trim();
@@ -9149,8 +9585,8 @@ function isNewerVersion(current, remote) {
9149
9585
  return remPatch > curPatch;
9150
9586
  }
9151
9587
  function getUpdateCachePath() {
9152
- const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join9(homedir9(), ".pikaa");
9153
- return join9(baseDir, "update-cache.json");
9588
+ const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join11(homedir9(), ".pikaa");
9589
+ return join11(baseDir, "update-cache.json");
9154
9590
  }
9155
9591
  async function fetchLatestNpmVersion(packageName, timeoutMs = 1500) {
9156
9592
  const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
@@ -9183,9 +9619,9 @@ async function checkForUpdates(options = {}) {
9183
9619
  const cachePath = options.cachePath || getUpdateCachePath();
9184
9620
  const now = Date.now();
9185
9621
  let cached = null;
9186
- if (!options.force && existsSync18(cachePath)) {
9622
+ if (!options.force && existsSync20(cachePath)) {
9187
9623
  try {
9188
- const raw = JSON.parse(readFileSync13(cachePath, "utf8"));
9624
+ const raw = JSON.parse(readFileSync14(cachePath, "utf8"));
9189
9625
  if (raw && typeof raw.lastChecked === "number" && typeof raw.latestVersion === "string") {
9190
9626
  cached = raw;
9191
9627
  if (now - cached.lastChecked < CHECK_INTERVAL_MS) {
@@ -9213,8 +9649,8 @@ async function checkForUpdates(options = {}) {
9213
9649
  return null;
9214
9650
  }
9215
9651
  try {
9216
- const parentDir = join9(cachePath, "..");
9217
- if (!existsSync18(parentDir)) {
9652
+ const parentDir = join11(cachePath, "..");
9653
+ if (!existsSync20(parentDir)) {
9218
9654
  mkdirSync10(parentDir, { recursive: true });
9219
9655
  }
9220
9656
  const cacheData = {
@@ -9222,7 +9658,7 @@ async function checkForUpdates(options = {}) {
9222
9658
  latestVersion,
9223
9659
  packageName
9224
9660
  };
9225
- writeFileSync7(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
9661
+ writeFileSync8(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
9226
9662
  } catch {}
9227
9663
  const updateAvailable = isNewerVersion(currentVersion, latestVersion);
9228
9664
  return updateAvailable ? {
@@ -9589,6 +10025,10 @@ async function main() {
9589
10025
  } else if (arg === "worktrees" || arg === "worktree") {
9590
10026
  await printWorktreesList(worktreeManager, cwd);
9591
10027
  process.exit(0);
10028
+ } else if (arg === "init") {
10029
+ const initResult = runProjectInit({ cwd });
10030
+ printInitSummary(initResult);
10031
+ process.exit(0);
9592
10032
  } else if (arg === "--resume" || arg === "-R" || arg === "resume") {
9593
10033
  resumeThreadId = args[++i];
9594
10034
  } else if (arg === "--model" || arg === "-m") {
@@ -9630,7 +10070,7 @@ async function main() {
9630
10070
  resolve21(cwd, "mcp_config.json")
9631
10071
  ].filter(Boolean);
9632
10072
  for (const cfg of candidateConfigs) {
9633
- if (existsSync19(cfg)) {
10073
+ if (existsSync21(cfg)) {
9634
10074
  try {
9635
10075
  await mcpManager.loadConfigFile(cfg);
9636
10076
  mcpManager.registerToolsIntoRouter(tools4);
@@ -9888,6 +10328,7 @@ ${style.bold("USAGE:")}
9888
10328
  groupy skills # List available domain skills
9889
10329
  groupy memories # View learned user preferences
9890
10330
  groupy worktrees # List active isolated Git Worktrees
10331
+ groupy init # Initialize or update AGENTS.md project instructions
9891
10332
 
9892
10333
  ${style.bold("OPTIONS:")}
9893
10334
  -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.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",
@@ -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).