create-chat-gpt-repo-memory 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,275 @@
1
+ # create-chat-gpt-repo-memory
2
+
3
+ `create-chat-gpt-repo-memory` scaffolds Git-tracked repo memory files for ChatGPT and Codex-style coding workflows.
4
+
5
+ It creates a root `AGENTS.md` instruction file plus a shared `.agent-memory/` folder containing durable project memory templates. The package scaffolds structure and template content only. It does not analyze the target repository.
6
+
7
+ ## Quickstart
8
+
9
+ ### Step 1 — scaffold the files
10
+
11
+ Run this inside any repository:
12
+
13
+ ```bash
14
+ npx create-chat-gpt-repo-memory
15
+ ```
16
+
17
+ This creates `AGENTS.md` and an `.agent-memory/` directory with template memory files, and updates `.gitignore` to exclude local agent cache files.
18
+
19
+ ### Step 2 — let ChatGPT fill them in
20
+
21
+ Open a ChatGPT session with access to your repository and run:
22
+
23
+ ```
24
+ Use AGENTS.md as your operating instructions for this repository. Then read .agent-memory/prompts/fill-project-map.md and execute it. Fill or update the .agent-memory files using only verified repository facts. Do not include secrets.
25
+ ```
26
+
27
+ ChatGPT will inspect your repository and populate the memory files with your actual stack, architecture, conventions, entry points, workflows, and more.
28
+
29
+ ### Step 3 — commit
30
+
31
+ ```bash
32
+ git add AGENTS.md .agent-memory/ .gitignore
33
+ git commit -m "Add ChatGPT repo memory"
34
+ ```
35
+
36
+ Done. Every future session that reads `AGENTS.md` and `.agent-memory/` will have full project context before doing anything else.
37
+
38
+ ## Why `AGENTS.md` Instead of `CHATGPT.md`
39
+
40
+ This package uses `AGENTS.md` because that is the Codex-style repository instruction convention.
41
+
42
+ That keeps one shared instruction surface for mixed workflows:
43
+
44
+ - Codex-style agents can start from `AGENTS.md`
45
+ - ChatGPT Projects can upload or reference the same files
46
+ - Teams can track one repo-memory structure in Git
47
+
48
+ This package does not generate `CHATGPT.md`.
49
+
50
+ ## Why `.agent-memory/` Instead of `.chatgpt/`
51
+
52
+ This package uses `.agent-memory/` as shared Git-tracked project memory:
53
+
54
+ - readable by humans and coding agents
55
+ - easy to version in Git
56
+ - neutral naming that works across tools
57
+ - separate from local cache artifacts
58
+
59
+ This package does not generate `.chatgpt/`.
60
+
61
+ ## Installation
62
+
63
+ Use with `npx`:
64
+
65
+ ```bash
66
+ npx create-chat-gpt-repo-memory
67
+ ```
68
+
69
+ Or install globally:
70
+
71
+ ```bash
72
+ npm install -g create-chat-gpt-repo-memory
73
+ create-chat-gpt-repo-memory
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ ```bash
79
+ npx create-chat-gpt-repo-memory
80
+ npx create-chat-gpt-repo-memory --template dotnet
81
+ npx create-chat-gpt-repo-memory --force
82
+ npx create-chat-gpt-repo-memory --no-gitignore
83
+ npx create-chat-gpt-repo-memory --cwd ../some-project
84
+ ```
85
+
86
+ ## Options
87
+
88
+ - `--force`: overwrite existing generated files
89
+ - `--no-gitignore`: skip `.gitignore` updates
90
+ - `--template <name>`: choose `generic` or `dotnet`
91
+ - `--cwd <path>`: target directory to scaffold into
92
+
93
+ ## Files Generated
94
+
95
+ ```text
96
+ AGENTS.md
97
+ .agent-memory/project-map.md
98
+ .agent-memory/architecture.md
99
+ .agent-memory/conventions.md
100
+ .agent-memory/workflows.md
101
+ .agent-memory/update-project-map.md
102
+ .agent-memory/prompts/fill-project-map.md
103
+ .agent-memory/prompts/start-session.md
104
+ ```
105
+
106
+ The package does not create `.agent-memory-local/`. That path is added to `.gitignore` only.
107
+
108
+ ## Template Options
109
+
110
+ - `generic`: baseline repository memory template
111
+ - `dotnet`: generic template plus .NET-specific guidance
112
+
113
+ Template variables:
114
+
115
+ - `{{PROJECT_NAME}}`
116
+ - `{{TEMPLATE_NAME}}`
117
+ - `{{GENERATED_BY}}`
118
+
119
+ ## Initial Map-Fill Prompt
120
+
121
+ ```text
122
+ Use AGENTS.md as your operating instructions for this repository. Then read .agent-memory/prompts/fill-project-map.md and execute it. Fill or update the .agent-memory files using only verified repository facts. Do not include secrets.
123
+ ```
124
+
125
+ ## Future Session-Start Prompt
126
+
127
+ ```text
128
+ Use AGENTS.md as your operating instructions, then read .agent-memory/prompts/start-session.md and follow it for this task.
129
+ ```
130
+
131
+ ## Overwrite Safety
132
+
133
+ The CLI never silently overwrites generated files.
134
+
135
+ - If a file does not exist, it is created.
136
+ - If a file exists and `--force` is not set, it is skipped by default.
137
+ - If a file exists and `--force` is set, it is overwritten.
138
+
139
+ For an existing `AGENTS.md`, the CLI is more careful:
140
+
141
+ - If the file does not already contain repo-memory guidance, the CLI appends a managed repo-memory instructions block instead of replacing the whole file.
142
+ - If that managed block already exists, the CLI updates just that block on later runs.
143
+ - If the existing `AGENTS.md` already contains its own repo-memory guidance and the CLI cannot safely merge it, the CLI asks whether to skip or overwrite when running interactively.
144
+ - In a non-interactive environment, that unmergeable case falls back to skip.
145
+
146
+ ## `.gitignore` Behavior
147
+
148
+ Unless `--no-gitignore` is used, the CLI updates or creates `.gitignore` and adds this local-only block when needed:
149
+
150
+ ```gitignore
151
+ # Local agent memory/cache
152
+ .agent-memory-local/
153
+ .agent-memory/**/*.db
154
+ .agent-memory/**/*.sqlite
155
+ .agent-memory/**/*.sqlite3
156
+ .agent-memory/**/*.log
157
+ ```
158
+
159
+ The update is idempotent. If `.gitignore` already contains `.agent-memory-local/`, the block is not appended again.
160
+
161
+ The package also removes legacy `.chatgpt-local/` and `.chatgpt/**/*.(db|sqlite|sqlite3|log)` ignore lines when it updates `.gitignore`.
162
+
163
+ The Git-tracked memory files themselves are never ignored by this package.
164
+
165
+ ## Notes for Codex-Style Usage
166
+
167
+ - `AGENTS.md` is the root instruction file.
168
+ - Codex-style agents should start from the repo root so `AGENTS.md` can be discovered.
169
+ - Keep `.agent-memory/project-map.md` concise and move detail into supporting memory files.
170
+
171
+ ## Notes for ChatGPT Project Usage
172
+
173
+ - ChatGPT Projects do not automatically treat `.agent-memory/` as a magic folder.
174
+ - Add `AGENTS.md` and `.agent-memory/` files to the project, or make sure they are available in repository context.
175
+ - Start future sessions by telling ChatGPT to read `AGENTS.md` and the relevant `.agent-memory/` files.
176
+
177
+ ## Publishing
178
+
179
+ ```bash
180
+ npm login
181
+ npm publish --access public
182
+ ```
183
+
184
+ ## Local Testing
185
+
186
+ ```bash
187
+ npm link
188
+ create-chat-gpt-repo-memory --cwd ../some-test-repo
189
+ ```
190
+
191
+ ## Manual Test Plan
192
+
193
+ Create a temporary test project:
194
+
195
+ ```bash
196
+ mkdir /tmp/chatgpt-memory-test
197
+ cd /tmp/chatgpt-memory-test
198
+ node /path/to/create-chat-gpt-repo-memory/bin/cli.js
199
+ ```
200
+
201
+ Verify:
202
+
203
+ ```text
204
+ AGENTS.md exists
205
+ .agent-memory/project-map.md exists
206
+ .agent-memory/architecture.md exists
207
+ .agent-memory/conventions.md exists
208
+ .agent-memory/workflows.md exists
209
+ .agent-memory/update-project-map.md exists
210
+ .agent-memory/prompts/fill-project-map.md exists
211
+ .agent-memory/prompts/start-session.md exists
212
+ .gitignore contains Local agent memory/cache block
213
+ ```
214
+
215
+ Run it again without `--force`.
216
+
217
+ Expected:
218
+
219
+ ```text
220
+ files are skipped
221
+ .gitignore is unchanged
222
+ no duplicate gitignore block
223
+ ```
224
+
225
+ Run with `--force`.
226
+
227
+ Expected:
228
+
229
+ ```text
230
+ existing generated files are overwritten
231
+ .gitignore remains unchanged
232
+ ```
233
+
234
+ Run with dotnet template:
235
+
236
+ ```bash
237
+ mkdir /tmp/chatgpt-memory-dotnet-test
238
+ node /path/to/create-chat-gpt-repo-memory/bin/cli.js --template dotnet --cwd /tmp/chatgpt-memory-dotnet-test
239
+ ```
240
+
241
+ Expected:
242
+
243
+ ```text
244
+ dotnet-specific sections are present
245
+ .agent-memory/prompts/start-session.md exists
246
+ ```
247
+
248
+ Run against an invalid template:
249
+
250
+ ```bash
251
+ node /path/to/create-chat-gpt-repo-memory/bin/cli.js --template invalid
252
+ ```
253
+
254
+ Expected:
255
+
256
+ ```text
257
+ clear unsupported-template error
258
+ exit code 1
259
+ ```
260
+
261
+ Search for stale terms:
262
+
263
+ ```bash
264
+ grep -R "CHATGPT.md\|\.chatgpt\|CLAUDE.md\|\.claude\|create-claude" .
265
+ ```
266
+
267
+ Expected:
268
+
269
+ ```text
270
+ No stale references, except intentional README explanation if present.
271
+ ```
272
+
273
+ ## License
274
+
275
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import { resolveTargetDirectory } from "../src/paths.js";
5
+ import { initChatGptRepoMemory } from "../src/init.js";
6
+ import { SUPPORTED_TEMPLATES } from "../src/templateResolver.js";
7
+
8
+ const program = new Command();
9
+
10
+ program
11
+ .name("create-chat-gpt-repo-memory")
12
+ .description("Scaffold Git-tracked repo memory files for ChatGPT and Codex-style coding workflows.")
13
+ .version("0.1.0");
14
+
15
+ function addOptions(cmd) {
16
+ return cmd
17
+ .option("--force", "Overwrite existing generated files.", false)
18
+ .option("--no-gitignore", "Do not update .gitignore.")
19
+ .option("--template <name>", `Template to use. Supported values: ${SUPPORTED_TEMPLATES.join(", ")}.`, "generic")
20
+ .option("--cwd <path>", "Directory where files should be created.", process.cwd());
21
+ }
22
+
23
+ async function runInit(options) {
24
+ const { force, gitignore: updateGitignore, template, cwd } = options;
25
+
26
+ let rootDir;
27
+ try {
28
+ rootDir = await resolveTargetDirectory(cwd);
29
+ } catch (err) {
30
+ console.error(`Error: ${err.message}`);
31
+ process.exit(1);
32
+ }
33
+
34
+ let result;
35
+ try {
36
+ result = await initChatGptRepoMemory({ rootDir, force, updateGitignore, template });
37
+ } catch (err) {
38
+ console.error(`Error: ${err.message}`);
39
+ process.exit(1);
40
+ }
41
+
42
+ const { created, overwritten, skipped, gitignoreStatus } = result;
43
+
44
+ console.log("\nChatGPT/Codex repo memory initialized.\n");
45
+
46
+ if (created.length > 0) {
47
+ console.log("Created:");
48
+ for (const f of created) console.log(` - ${f}`);
49
+ console.log();
50
+ }
51
+
52
+ if (overwritten.length > 0) {
53
+ console.log("Overwritten:");
54
+ for (const f of overwritten) console.log(` - ${f}`);
55
+ console.log();
56
+ }
57
+
58
+ if (skipped.length > 0) {
59
+ console.log("Skipped:");
60
+ for (const f of skipped) console.log(` - ${f}`);
61
+ console.log();
62
+ }
63
+
64
+ console.log(`Gitignore: ${gitignoreStatus}\n`);
65
+
66
+ console.log("Next steps:");
67
+ console.log(" 1. Commit AGENTS.md and .agent-memory/ files.");
68
+ console.log(" 2. For Codex-style agents, start from the repo root so the agent can read AGENTS.md.");
69
+ console.log(" 3. For ChatGPT Projects, add AGENTS.md and .agent-memory/ as project files or make sure they are available in the repository context.");
70
+ console.log(' 4. Kick off the initial map fill with:');
71
+ console.log(' "Use AGENTS.md as your operating instructions for this repository. Then read .agent-memory/prompts/fill-project-map.md and execute it. Fill or update the .agent-memory files using only verified repository facts. Do not include secrets."');
72
+ console.log();
73
+ }
74
+
75
+ addOptions(program);
76
+
77
+ program.action(async () => {
78
+ await runInit(program.opts());
79
+ });
80
+
81
+ program.parseAsync(process.argv).catch((err) => {
82
+ console.error(`Error: ${err.message}`);
83
+ process.exit(1);
84
+ });
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "create-chat-gpt-repo-memory",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold Git-tracked repo memory files for ChatGPT and Codex-style coding workflows.",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-chat-gpt-repo-memory": "./bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "templates",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "keywords": [
20
+ "chatgpt",
21
+ "codex",
22
+ "openai",
23
+ "ai",
24
+ "agents",
25
+ "repository",
26
+ "project-map",
27
+ "repo-memory",
28
+ "developer-tools",
29
+ "cli"
30
+ ],
31
+ "license": "MIT",
32
+ "dependencies": {
33
+ "commander": "^12.1.0"
34
+ }
35
+ }
@@ -0,0 +1,81 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ const GITIGNORE_MARKER = ".agent-memory-local/";
5
+ const GITIGNORE_BLOCK = [
6
+ "# Local agent memory/cache",
7
+ ".agent-memory-local/",
8
+ ".agent-memory/**/*.db",
9
+ ".agent-memory/**/*.sqlite",
10
+ ".agent-memory/**/*.sqlite3",
11
+ ".agent-memory/**/*.log"
12
+ ].join("\n");
13
+
14
+ const LEGACY_PREFIX = "\\." + "chatgpt";
15
+ const LEGACY_PATTERNS = [
16
+ new RegExp("^# .*" + "chatgpt" + ".*$", "i"),
17
+ new RegExp(`^${LEGACY_PREFIX}-local/$`),
18
+ new RegExp(`^${LEGACY_PREFIX}/\\*\\*/\\*\\.db$`),
19
+ new RegExp(`^${LEGACY_PREFIX}/\\*\\*/\\*\\.sqlite$`),
20
+ new RegExp(`^${LEGACY_PREFIX}/\\*\\*/\\*\\.sqlite3$`),
21
+ new RegExp(`^${LEGACY_PREFIX}/\\*\\*/\\*\\.log$`)
22
+ ];
23
+
24
+ function stripLegacyLines(content) {
25
+ const lines = content.replace(/\r\n/g, "\n").split("\n");
26
+ const filtered = [];
27
+ let changed = false;
28
+
29
+ for (const line of lines) {
30
+ const isLegacy = LEGACY_PATTERNS.some((pattern) => pattern.test(line.trim()));
31
+ if (isLegacy) {
32
+ changed = true;
33
+ continue;
34
+ }
35
+
36
+ filtered.push(line);
37
+ }
38
+
39
+ const normalized = filtered.join("\n").replace(/\n{3,}/g, "\n\n");
40
+ return {
41
+ changed,
42
+ content: normalized
43
+ };
44
+ }
45
+
46
+ function appendManagedBlock(content) {
47
+ const trimmed = content.replace(/\s*$/, "");
48
+ if (trimmed.length === 0) {
49
+ return `${GITIGNORE_BLOCK}\n`;
50
+ }
51
+
52
+ return `${trimmed}\n\n${GITIGNORE_BLOCK}\n`;
53
+ }
54
+
55
+ export async function updateGitignoreFile(rootDir) {
56
+ const gitignorePath = path.join(rootDir, ".gitignore");
57
+ let current = "";
58
+
59
+ try {
60
+ current = await fs.readFile(gitignorePath, "utf8");
61
+ } catch (error) {
62
+ if (error && error.code !== "ENOENT") {
63
+ throw error;
64
+ }
65
+ }
66
+
67
+ const { changed: removedLegacy, content: withoutLegacy } = stripLegacyLines(current);
68
+
69
+ if (withoutLegacy.includes(GITIGNORE_MARKER)) {
70
+ if (!removedLegacy) {
71
+ return "unchanged";
72
+ }
73
+
74
+ await fs.writeFile(gitignorePath, `${withoutLegacy.replace(/\s*$/, "")}\n`, "utf8");
75
+ return "updated";
76
+ }
77
+
78
+ const nextContent = appendManagedBlock(withoutLegacy);
79
+ await fs.writeFile(gitignorePath, nextContent, "utf8");
80
+ return "updated";
81
+ }
package/src/init.js ADDED
@@ -0,0 +1,205 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { createInterface } from "node:readline/promises";
4
+ import { updateGitignoreFile } from "./gitignore.js";
5
+ import { getProjectName } from "./projectName.js";
6
+ import { getPackageRoot } from "./paths.js";
7
+ import { applyTemplateVariables, validateTemplateName } from "./templateResolver.js";
8
+
9
+ const GENERATED_BY = "create-chat-gpt-repo-memory";
10
+ const MANAGED_AGENTS_START = "<!-- create-chat-gpt-repo-memory:start -->";
11
+ const MANAGED_AGENTS_END = "<!-- create-chat-gpt-repo-memory:end -->";
12
+
13
+ const FILES_TO_GENERATE = [
14
+ { source: "AGENTS.md", target: "AGENTS.md" },
15
+ { source: "project-map.md", target: ".agent-memory/project-map.md" },
16
+ { source: "architecture.md", target: ".agent-memory/architecture.md" },
17
+ { source: "conventions.md", target: ".agent-memory/conventions.md" },
18
+ { source: "workflows.md", target: ".agent-memory/workflows.md" },
19
+ { source: "update-project-map.md", target: ".agent-memory/update-project-map.md" },
20
+ { source: "prompts/fill-project-map.md", target: ".agent-memory/prompts/fill-project-map.md" },
21
+ { source: "prompts/start-session.md", target: ".agent-memory/prompts/start-session.md" }
22
+ ];
23
+
24
+ const packageRoot = getPackageRoot();
25
+
26
+ function normalizeNewlines(content) {
27
+ return content.replace(/\r\n/g, "\n");
28
+ }
29
+
30
+ function createManagedAgentsBlock(renderedTemplate) {
31
+ const body = normalizeNewlines(renderedTemplate)
32
+ .replace(/^# .*?\n+/, "")
33
+ .trim();
34
+
35
+ return [
36
+ MANAGED_AGENTS_START,
37
+ "## Repo Memory Instructions",
38
+ "",
39
+ body,
40
+ MANAGED_AGENTS_END
41
+ ].join("\n");
42
+ }
43
+
44
+ function isRepoMemoryAwareAgentsFile(content) {
45
+ return [
46
+ ".agent-memory/project-map.md",
47
+ ".agent-memory/",
48
+ "Use AGENTS.md as your operating instructions",
49
+ "Project Memory Workflow"
50
+ ].some((needle) => content.includes(needle));
51
+ }
52
+
53
+ async function promptForAgentsConflict(relativeTarget) {
54
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
55
+ return "skip";
56
+ }
57
+
58
+ const readline = createInterface({
59
+ input: process.stdin,
60
+ output: process.stdout
61
+ });
62
+
63
+ try {
64
+ while (true) {
65
+ const answer = (await readline.question(
66
+ `${relativeTarget} already exists and could not be merged automatically. Choose [s]kip or [o]verwrite: `
67
+ ))
68
+ .trim()
69
+ .toLowerCase();
70
+
71
+ if (answer === "s" || answer === "skip") {
72
+ return "skip";
73
+ }
74
+
75
+ if (answer === "o" || answer === "overwrite") {
76
+ return "overwrite";
77
+ }
78
+ }
79
+ } finally {
80
+ readline.close();
81
+ }
82
+ }
83
+
84
+ async function handleExistingAgentsFile({
85
+ targetPath,
86
+ relativeTarget,
87
+ existingContent,
88
+ renderedContent,
89
+ result
90
+ }) {
91
+ const normalizedExisting = normalizeNewlines(existingContent);
92
+ const managedBlock = createManagedAgentsBlock(renderedContent);
93
+
94
+ if (
95
+ normalizedExisting.includes(MANAGED_AGENTS_START) &&
96
+ normalizedExisting.includes(MANAGED_AGENTS_END)
97
+ ) {
98
+ const nextContent = normalizedExisting.replace(
99
+ new RegExp(
100
+ `${MANAGED_AGENTS_START.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${MANAGED_AGENTS_END.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`
101
+ ),
102
+ managedBlock
103
+ );
104
+
105
+ if (nextContent === normalizedExisting) {
106
+ result.skipped.push(relativeTarget);
107
+ return;
108
+ }
109
+
110
+ await fs.writeFile(targetPath, nextContent, "utf8");
111
+ result.overwritten.push(`${relativeTarget} (merged)`);
112
+ return;
113
+ }
114
+
115
+ if (!isRepoMemoryAwareAgentsFile(existingContent)) {
116
+ const nextContent = `${normalizedExisting.trimEnd()}\n\n${managedBlock}\n`;
117
+ await fs.writeFile(targetPath, nextContent, "utf8");
118
+ result.overwritten.push(`${relativeTarget} (merged)`);
119
+ return;
120
+ }
121
+
122
+ const choice = await promptForAgentsConflict(relativeTarget);
123
+
124
+ if (choice === "overwrite") {
125
+ await fs.writeFile(targetPath, renderedContent, "utf8");
126
+ result.overwritten.push(relativeTarget);
127
+ return;
128
+ }
129
+
130
+ result.skipped.push(relativeTarget);
131
+ }
132
+
133
+ export async function initChatGptRepoMemory(options) {
134
+ const rootDir = path.resolve(options.rootDir);
135
+ const template = options.template ?? "generic";
136
+
137
+ validateTemplateName(template);
138
+
139
+ const variables = {
140
+ PROJECT_NAME: getProjectName(rootDir),
141
+ TEMPLATE_NAME: template,
142
+ GENERATED_BY: GENERATED_BY
143
+ };
144
+
145
+ const result = {
146
+ rootDir,
147
+ template,
148
+ created: [],
149
+ overwritten: [],
150
+ skipped: [],
151
+ gitignoreStatus: "skipped"
152
+ };
153
+
154
+ for (const file of FILES_TO_GENERATE) {
155
+ const templatePath = path.join(packageRoot, "templates", template, file.source);
156
+ const targetPath = path.join(rootDir, file.target);
157
+ const relativeTarget = path.relative(rootDir, targetPath) || file.target;
158
+ const templateContent = await fs.readFile(templatePath, "utf8");
159
+ const rendered = applyTemplateVariables(templateContent, variables);
160
+
161
+ await fs.mkdir(path.dirname(targetPath), { recursive: true });
162
+
163
+ let exists = false;
164
+ try {
165
+ await fs.access(targetPath);
166
+ exists = true;
167
+ } catch (error) {
168
+ if (error && error.code !== "ENOENT") {
169
+ throw error;
170
+ }
171
+ }
172
+
173
+ if (!exists) {
174
+ await fs.writeFile(targetPath, rendered, "utf8");
175
+ result.created.push(relativeTarget.replace(/\\/g, "/"));
176
+ continue;
177
+ }
178
+
179
+ if (options.force) {
180
+ await fs.writeFile(targetPath, rendered, "utf8");
181
+ result.overwritten.push(relativeTarget.replace(/\\/g, "/"));
182
+ continue;
183
+ }
184
+
185
+ if (file.target === "AGENTS.md") {
186
+ const existingContent = await fs.readFile(targetPath, "utf8");
187
+ await handleExistingAgentsFile({
188
+ targetPath,
189
+ relativeTarget: relativeTarget.replace(/\\/g, "/"),
190
+ existingContent,
191
+ renderedContent: rendered,
192
+ result
193
+ });
194
+ continue;
195
+ }
196
+
197
+ result.skipped.push(relativeTarget.replace(/\\/g, "/"));
198
+ }
199
+
200
+ if (options.updateGitignore) {
201
+ result.gitignoreStatus = await updateGitignoreFile(rootDir);
202
+ }
203
+
204
+ return result;
205
+ }