mkctx 1.0.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.
Files changed (5) hide show
  1. package/README.md +176 -0
  2. package/cleanup.js +28 -0
  3. package/install.js +134 -0
  4. package/main.go +210 -0
  5. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # mkctx - Make Context
2
+
3
+ A powerful command-line tool that generates comprehensive markdown context files from your project code, perfect for use with AI assistants and documentation.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Multi-platform** - Works on Windows, macOS, and Linux
8
+ - 📝 **Smart Ignoring** - Respects gitignore patterns and custom ignore rules
9
+ - ⚙️ **Configurable** - Customize source directories, output locations, and comments
10
+ - 🎯 **AI-Friendly** - Outputs code in markdown format ideal for AI prompts
11
+ - 🔧 **Easy Installation** - Install globally via npm
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install -g mkctx
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### Generate context for your project
22
+ ```bash
23
+ mkctx
24
+ ```
25
+
26
+ ### Create configuration file
27
+ ```bash
28
+ mkctx config
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### Basic Usage
34
+ Run `mkctx` in your project root to generate a `context.md` file containing all your project code:
35
+
36
+ ```bash
37
+ cd your-project/
38
+ mkctx
39
+ ```
40
+
41
+ ### Configuration
42
+ Create a configuration file to customize behavior:
43
+
44
+ ```bash
45
+ mkctx config
46
+ ```
47
+
48
+ This creates:
49
+ - `mkctx.config.json` - Configuration file
50
+ - `mkctx/` directory - Output folder (added to .gitignore)
51
+
52
+ ## Configuration Options
53
+
54
+ The `mkctx.config.json` file supports the following options:
55
+
56
+ ```json
57
+ {
58
+ "src": "./src",
59
+ "ignore": "*.log, temp/, node_modules/, .git/",
60
+ "output": "./mkctx",
61
+ "first_comment": "/* Project Context */",
62
+ "last_comment": "/* End of Context */"
63
+ }
64
+ ```
65
+
66
+ | Option | Description | Default |
67
+ |--------|-------------|---------|
68
+ | `src` | Source directory to scan | `"."` (current directory) |
69
+ | `ignore` | Comma-separated patterns to ignore | `"*.log, temp/, node_modules/, .git/"` |
70
+ | `output` | Output directory for context file | `"."` (current directory) |
71
+ | `first_comment` | Comment added at the beginning of the context | `"/* Project Context */"` |
72
+ | `last_comment` | Comment added at the end of the context | `"/* End of Context */"` |
73
+
74
+ ## Output Format
75
+
76
+ The generated `context.md` file contains your project code in this format:
77
+
78
+ ````markdown
79
+ /* Project Context */
80
+
81
+ ```javascript
82
+ // src/main.js
83
+ console.log("Hello World!");
84
+ ```
85
+
86
+ ```css
87
+ // styles/main.css
88
+ body { margin: 0; }
89
+ ```
90
+
91
+ /* End of Context */
92
+ ````
93
+
94
+ ## Examples
95
+
96
+ ### Include only specific directories
97
+ ```json
98
+ {
99
+ "src": "./src",
100
+ "ignore": "*.test.js, __tests__/, dist/",
101
+ "output": "./docs",
102
+ "first_comment": "/* My App Codebase */"
103
+ }
104
+ ```
105
+
106
+ ### Generate context for documentation
107
+ ```json
108
+ {
109
+ "src": ".",
110
+ "ignore": "node_modules/, .git/, *.md, package-lock.json",
111
+ "first_comment": "## Project Overview\n\nThis is the complete codebase for my application.",
112
+ "last_comment": "## End of Codebase\n\nThis context file was generated using mkctx."
113
+ }
114
+ ```
115
+
116
+ ## Platform Support
117
+
118
+ - ✅ **Windows** - Full support with automatic .exe handling
119
+ - ✅ **macOS** - Native support with proper permissions
120
+ - ✅ **Linux** - Complete compatibility
121
+
122
+ ## Requirements
123
+
124
+ - **Go** 1.16+ (for building from source)
125
+ - **Node.js** 14.0+ (for npm installation)
126
+ - **npm** or **yarn** (for package management)
127
+
128
+ ## How It Works
129
+
130
+ 1. **Scan**: Recursively scans your source directory
131
+ 2. **Filter**: Applies ignore patterns from config and .gitignore
132
+ 3. **Format**: Converts each file to markdown code blocks with file paths
133
+ 4. **Output**: Generates a comprehensive context.md file
134
+
135
+ ## Use Cases
136
+
137
+ - **AI Pair Programming** - Provide complete context to AI assistants
138
+ - **Code Reviews** - Share project overview with reviewers
139
+ - **Documentation** - Create living documentation of your codebase
140
+ - **Onboarding** - Help new developers understand the project structure
141
+ - **Backup** - Generate searchable archives of your code
142
+
143
+ ## Troubleshooting
144
+
145
+ ### Installation Issues
146
+ If installation fails, try manual installation:
147
+ 1. Build the binary: `go build -o mkctx main.go`
148
+ 2. Copy to a directory in your PATH
149
+ 3. Ensure execution permissions: `chmod +x mkctx`
150
+
151
+ ### Permission Errors
152
+ On Unix systems, you might need to use `sudo`:
153
+ ```bash
154
+ sudo npm install -g mkctx
155
+ ```
156
+
157
+ ### Binary Not Found
158
+ If `mkctx` command is not found after installation:
159
+ 1. Check if the installation directory is in your PATH
160
+ 2. Restart your terminal
161
+ 3. Try reinstalling: `npm uninstall -g mkctx && npm install -g mkctx`
162
+
163
+ ## Contributing
164
+
165
+ Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
166
+
167
+ ## License
168
+
169
+ MIT License - see LICENSE file for details.
170
+
171
+ ## Support
172
+
173
+ If you encounter any problems or have questions:
174
+ 1. Check this README for solutions
175
+ 2. Open an issue on GitHub
176
+ 3. Check the generated configuration for guidance
package/cleanup.js ADDED
@@ -0,0 +1,28 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ function cleanup() {
5
+ const filesToRemove = ["mkctx", "mkctx.exe"];
6
+ let removedCount = 0;
7
+
8
+ filesToRemove.forEach((file) => {
9
+ const filePath = path.join(__dirname, file);
10
+ try {
11
+ if (fs.existsSync(filePath)) {
12
+ fs.unlinkSync(filePath);
13
+ console.log(`🧹 Cleaning up: ${file}`);
14
+ removedCount++;
15
+ }
16
+ } catch (error) {
17
+ console.log(`⚠️ Could not delete ${file}: ${error.message}`);
18
+ }
19
+ });
20
+
21
+ if (removedCount > 0) {
22
+ console.log(`✅ Cleaned up ${removedCount} temporary files`);
23
+ } else {
24
+ console.log(`ℹ️ No temporary files found to clean up`);
25
+ }
26
+ }
27
+
28
+ cleanup();
package/install.js ADDED
@@ -0,0 +1,134 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const { execSync } = require("child_process");
4
+
5
+ function install() {
6
+ const binaryName = process.platform === "win32" ? "mkctx.exe" : "mkctx";
7
+ const sourceBinary = process.platform === "win32" ? "mkctx.exe" : "mkctx";
8
+ const sourcePath = path.join(__dirname, sourceBinary);
9
+
10
+ // Rename the binary if necessary (from mkctx to mkctx.exe on Windows)
11
+ if (
12
+ process.platform === "win32" &&
13
+ fs.existsSync("mkctx") &&
14
+ !fs.existsSync("mkctx.exe")
15
+ ) {
16
+ fs.renameSync("mkctx", "mkctx.exe");
17
+ console.log("✅ Binary renamed for Windows: mkctx -> mkctx.exe");
18
+ }
19
+
20
+ // Check if the binary exists
21
+ if (!fs.existsSync(sourcePath)) {
22
+ console.log("❌ Compiled binary not found at:", sourcePath);
23
+ console.log("📋 Files in directory:");
24
+ try {
25
+ const files = fs.readdirSync(__dirname);
26
+ files.forEach((file) => console.log(" -", file));
27
+ } catch (e) {
28
+ console.log(" Could not read directory");
29
+ }
30
+ return;
31
+ }
32
+
33
+ try {
34
+ // Method 1: Use npm to get the global bin directory
35
+ const npmGlobalBin = execSync("npm bin -g").toString().trim();
36
+ const installPath = path.join(npmGlobalBin, binaryName);
37
+
38
+ console.log(`📦 Installing mkctx at: ${installPath}`);
39
+
40
+ // Copy the binary
41
+ fs.copyFileSync(sourcePath, installPath);
42
+
43
+ // Set execution permissions (Unix only)
44
+ if (process.platform !== "win32") {
45
+ fs.chmodSync(installPath, 0o755);
46
+ }
47
+
48
+ console.log("✅ mkctx installed successfully via npm");
49
+ return;
50
+ } catch (error) {
51
+ console.log("⚠️ npm method failed, trying alternative method...");
52
+ }
53
+
54
+ // Alternative method: Search common PATH directories
55
+ const alternativePaths = getAlternativePaths();
56
+
57
+ for (const altPath of alternativePaths) {
58
+ try {
59
+ if (fs.existsSync(altPath)) {
60
+ const altInstallPath = path.join(altPath, binaryName);
61
+ console.log(`🔄 Trying to install at: ${altInstallPath}`);
62
+
63
+ fs.copyFileSync(sourcePath, altInstallPath);
64
+
65
+ // Set execution permissions (Unix only)
66
+ if (process.platform !== "win32") {
67
+ fs.chmodSync(altInstallPath, 0o755);
68
+ }
69
+
70
+ console.log(`✅ mkctx installed at: ${altInstallPath}`);
71
+ return;
72
+ }
73
+ } catch (e) {
74
+ console.log(` ❌ Installation failed at ${altPath}: ${e.message}`);
75
+ // Continue to next path
76
+ }
77
+ }
78
+
79
+ // If we get here, all methods failed
80
+ console.log("❌ Could not install automatically");
81
+ console.log("📋 Manual installation required:");
82
+ console.log(` 1. Copy the file '${sourcePath}' to a folder in your PATH`);
83
+ console.log(` 2. Make sure the file has execution permissions`);
84
+
85
+ // Show current PATH to help the user
86
+ console.log("\n📁 Your PATH includes these folders:");
87
+ const pathDirs = process.env.PATH
88
+ ? process.env.PATH.split(path.delimiter)
89
+ : [];
90
+ pathDirs.forEach((dir) => console.log(" -", dir));
91
+ }
92
+
93
+ function getAlternativePaths() {
94
+ const paths = [];
95
+
96
+ if (process.platform === "win32") {
97
+ // Windows
98
+ if (process.env.APPDATA) {
99
+ paths.push(path.join(process.env.APPDATA, "npm"));
100
+ }
101
+ if (process.env.LOCALAPPDATA) {
102
+ paths.push(
103
+ path.join(process.env.LOCALAPPDATA, "Microsoft", "WindowsApps")
104
+ );
105
+ }
106
+ if (process.env.ProgramFiles) {
107
+ paths.push(path.join(process.env.ProgramFiles, "nodejs"));
108
+ }
109
+ // Add common Windows PATH directories
110
+ paths.push("C:\\Program Files\\nodejs");
111
+ paths.push("C:\\Program Files (x86)\\nodejs");
112
+ } else {
113
+ // Unix/Linux/macOS
114
+ paths.push("/usr/local/bin");
115
+ paths.push("/usr/bin");
116
+ paths.push("/opt/local/bin");
117
+
118
+ // User bin directory
119
+ if (process.env.HOME) {
120
+ paths.push(path.join(process.env.HOME, "bin"));
121
+ paths.push(path.join(process.env.HOME, ".local", "bin"));
122
+ }
123
+
124
+ // Common directories on macOS
125
+ if (process.platform === "darwin") {
126
+ paths.push("/opt/homebrew/bin");
127
+ paths.push("/usr/local/opt/bin");
128
+ }
129
+ }
130
+
131
+ return paths.filter((p) => p !== null && p !== undefined);
132
+ }
133
+
134
+ install();
package/main.go ADDED
@@ -0,0 +1,210 @@
1
+ package main
2
+
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "os"
7
+ "path/filepath"
8
+ "strings"
9
+ )
10
+
11
+ type Config struct {
12
+ Src string `json:"src"`
13
+ Ignore string `json:"ignore"`
14
+ Output string `json:"output"`
15
+ FirstComment string `json:"first_comment"`
16
+ LastComment string `json:"last_comment"`
17
+ }
18
+
19
+ func main() {
20
+ if len(os.Args) > 1 && os.Args[1] == "config" {
21
+ createConfig()
22
+ return
23
+ }
24
+ generateContext()
25
+ }
26
+
27
+ func createConfig() {
28
+ config := Config{
29
+ Src: "./src",
30
+ Ignore: "*.log, temp/, node_modules/, .git/",
31
+ Output: "./mkctx",
32
+ FirstComment: "/* Project Context */",
33
+ LastComment: "/* End of Context */",
34
+ }
35
+
36
+ configJSON, _ := json.MarshalIndent(config, "", " ")
37
+
38
+ // Create mkctx directory if it doesn't exist
39
+ _ = os.MkdirAll("mkctx", 0755)
40
+
41
+ // Write configuration file
42
+ _ = os.WriteFile("mkctx.config.json", configJSON, 0644)
43
+
44
+ // Update .gitignore
45
+ updateGitignore()
46
+
47
+ fmt.Println("✅ Configuration created:")
48
+ fmt.Println(" - mkctx.config.json")
49
+ fmt.Println(" - mkctx/ folder")
50
+ fmt.Println(" - Entry in .gitignore")
51
+ }
52
+
53
+ func updateGitignore() {
54
+ gitignorePath := ".gitignore"
55
+ content, err := os.ReadFile(gitignorePath)
56
+ gitignoreExists := err == nil
57
+
58
+ var newContent string
59
+ if gitignoreExists {
60
+ newContent = string(content)
61
+ if !strings.Contains(newContent, "mkctx/") {
62
+ newContent += "\n# mkctx - generated context\nmkctx/\n"
63
+ }
64
+ } else {
65
+ newContent = "# mkctx - generated context\nmkctx/\n"
66
+ }
67
+
68
+ _ = os.WriteFile(gitignorePath, []byte(newContent), 0644)
69
+ }
70
+
71
+ func generateContext() {
72
+ config := loadConfig()
73
+ files := getFiles(config)
74
+ content := buildContent(files, config)
75
+
76
+ outputPath := config.Output
77
+ if outputPath == "" {
78
+ outputPath = "."
79
+ }
80
+
81
+ // Ensure output directory exists
82
+ _ = os.MkdirAll(outputPath, 0755)
83
+
84
+ outputFile := filepath.Join(outputPath, "context.md")
85
+ err := os.WriteFile(outputFile, []byte(content), 0644)
86
+ if err != nil {
87
+ fmt.Printf("❌ Error creating file: %v\n", err)
88
+ return
89
+ }
90
+ fmt.Printf("✅ Context generated at: %s\n", outputFile)
91
+ }
92
+
93
+ func loadConfig() Config {
94
+ var config Config
95
+ file, err := os.ReadFile("mkctx.config.json")
96
+ if err != nil {
97
+ return getDefaultConfig()
98
+ }
99
+ json.Unmarshal(file, &config)
100
+
101
+ // Validate and complete configuration
102
+ if config.Src == "" {
103
+ config.Src = "."
104
+ }
105
+ if config.Output == "" {
106
+ config.Output = "."
107
+ }
108
+
109
+ return config
110
+ }
111
+
112
+ func getDefaultConfig() Config {
113
+ return Config{
114
+ Src: ".",
115
+ Output: ".",
116
+ FirstComment: "/* Project Context */",
117
+ LastComment: "/* End of Context */",
118
+ }
119
+ }
120
+
121
+ func getFiles(config Config) []string {
122
+ var files []string
123
+
124
+ srcPath := config.Src
125
+ if srcPath == "" {
126
+ srcPath = "."
127
+ }
128
+
129
+ filepath.Walk(srcPath, func(path string, info os.FileInfo, err error) error {
130
+ if err != nil || shouldIgnore(path, config) || info.IsDir() {
131
+ return nil
132
+ }
133
+ files = append(files, path)
134
+ return nil
135
+ })
136
+ return files
137
+ }
138
+
139
+ func shouldIgnore(path string, config Config) bool {
140
+ // Ignore system files
141
+ if strings.Contains(path, ".git") ||
142
+ strings.Contains(path, ".DS_Store") ||
143
+ strings.Contains(path, "Thumbs.db") {
144
+ return true
145
+ }
146
+
147
+ // Ignore based on configuration
148
+ if config.Ignore != "" {
149
+ ignorePatterns := strings.Split(config.Ignore, ",")
150
+ for _, pattern := range ignorePatterns {
151
+ pattern = strings.TrimSpace(pattern)
152
+ if pattern == "" {
153
+ continue
154
+ }
155
+
156
+ // Simple pattern with wildcard
157
+ if strings.Contains(pattern, "*") {
158
+ if matched, _ := filepath.Match(pattern, filepath.Base(path)); matched {
159
+ return true
160
+ }
161
+ }
162
+
163
+ // Entire directory
164
+ if strings.HasSuffix(pattern, "/") {
165
+ dir := strings.TrimSuffix(pattern, "/")
166
+ if strings.Contains(path, dir) {
167
+ return true
168
+ }
169
+ }
170
+
171
+ // Exact match
172
+ if strings.Contains(path, pattern) {
173
+ return true
174
+ }
175
+ }
176
+ }
177
+
178
+ return false
179
+ }
180
+
181
+ func buildContent(files []string, config Config) string {
182
+ var content strings.Builder
183
+
184
+ if config.FirstComment != "" {
185
+ content.WriteString(config.FirstComment + "\n\n")
186
+ }
187
+
188
+ for _, file := range files {
189
+ fileContent, err := os.ReadFile(file)
190
+ if err != nil {
191
+ continue
192
+ }
193
+
194
+ ext := filepath.Ext(file)
195
+ lang := "text"
196
+ if ext != "" {
197
+ lang = ext[1:] // Remove the dot
198
+ }
199
+
200
+ content.WriteString("```" + lang + "\n")
201
+ content.WriteString("// " + file + "\n")
202
+ content.WriteString(string(fileContent))
203
+ content.WriteString("\n```\n\n")
204
+ }
205
+
206
+ if config.LastComment != "" {
207
+ content.WriteString(config.LastComment)
208
+ }
209
+ return content.String()
210
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "mkctx",
3
+ "version": "1.0.0",
4
+ "description": "Tool to generate project context in markdown for AI assistants",
5
+ "main": "main.go",
6
+ "scripts": {
7
+ "preinstall": "go build -o mkctx main.go",
8
+ "install": "node install.js",
9
+ "postinstall": "node cleanup.js"
10
+ },
11
+ "keywords": [
12
+ "context",
13
+ "markdown",
14
+ "documentation",
15
+ "ai",
16
+ "prompt",
17
+ "code-context",
18
+ "development",
19
+ "tool"
20
+ ],
21
+ "author": "Tu Nombre <tu.email@example.com>",
22
+ "license": "MIT",
23
+ "bin": {
24
+ "mkctx": "./mkctx"
25
+ },
26
+ "files": [
27
+ "main.go",
28
+ "package.json",
29
+ "install.js",
30
+ "cleanup.js",
31
+ "README.md"
32
+ ],
33
+ "engines": {
34
+ "node": ">=14.0.0",
35
+ "go": ">=1.16"
36
+ },
37
+ "os": [
38
+ "darwin",
39
+ "linux",
40
+ "win32"
41
+ ],
42
+ "cpu": [
43
+ "x64",
44
+ "arm64"
45
+ ],
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/David200197/mkctx.git"
49
+ },
50
+ "homepage": "https://github.com/David200197/mkctx#readme",
51
+ "bugs": {
52
+ "url": "https://github.com/David200197/mkctx/issues"
53
+ }
54
+ }