codemaxxing 1.0.0 → 1.0.2

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 (47) hide show
  1. package/README.md +18 -12
  2. package/dist/agent.d.ts +4 -0
  3. package/dist/agent.js +91 -16
  4. package/dist/commands/git.d.ts +2 -0
  5. package/dist/commands/git.js +50 -0
  6. package/dist/commands/ollama.d.ts +27 -0
  7. package/dist/commands/ollama.js +171 -0
  8. package/dist/commands/output.d.ts +2 -0
  9. package/dist/commands/output.js +18 -0
  10. package/dist/commands/registry.d.ts +2 -0
  11. package/dist/commands/registry.js +8 -0
  12. package/dist/commands/skills.d.ts +18 -0
  13. package/dist/commands/skills.js +121 -0
  14. package/dist/commands/types.d.ts +5 -0
  15. package/dist/commands/types.js +1 -0
  16. package/dist/commands/ui.d.ts +16 -0
  17. package/dist/commands/ui.js +79 -0
  18. package/dist/config.d.ts +9 -0
  19. package/dist/config.js +13 -3
  20. package/dist/exec.js +4 -1
  21. package/dist/index.js +75 -401
  22. package/dist/tools/files.js +58 -3
  23. package/dist/utils/context.js +6 -0
  24. package/dist/utils/mcp.d.ts +7 -2
  25. package/dist/utils/mcp.js +34 -6
  26. package/package.json +8 -5
  27. package/src/agent.ts +0 -894
  28. package/src/auth-cli.ts +0 -287
  29. package/src/cli.ts +0 -37
  30. package/src/config.ts +0 -352
  31. package/src/exec.ts +0 -183
  32. package/src/index.tsx +0 -2647
  33. package/src/skills/registry.ts +0 -1436
  34. package/src/themes.ts +0 -335
  35. package/src/tools/files.ts +0 -374
  36. package/src/utils/auth.ts +0 -606
  37. package/src/utils/context.ts +0 -174
  38. package/src/utils/git.ts +0 -117
  39. package/src/utils/hardware.ts +0 -131
  40. package/src/utils/lint.ts +0 -116
  41. package/src/utils/mcp.ts +0 -307
  42. package/src/utils/models.ts +0 -218
  43. package/src/utils/ollama.ts +0 -352
  44. package/src/utils/repomap.ts +0 -220
  45. package/src/utils/sessions.ts +0 -254
  46. package/src/utils/skills.ts +0 -241
  47. package/tsconfig.json +0 -16
@@ -1,174 +0,0 @@
1
- import { existsSync, readFileSync, readdirSync, statSync } from "fs";
2
- import { join, extname } from "path";
3
- import { buildRepoMap } from "./repomap.js";
4
- import { buildSkillPrompts } from "./skills.js";
5
-
6
- /**
7
- * Load project rules from CODEMAXXING.md, .codemaxxing/CODEMAXXING.md, or .cursorrules
8
- * Returns { content, source } or null if none found
9
- */
10
- export function loadProjectRules(cwd: string): { content: string; source: string } | null {
11
- const candidates = [
12
- { path: join(cwd, "CODEMAXXING.md"), source: "CODEMAXXING.md" },
13
- { path: join(cwd, ".codemaxxing", "CODEMAXXING.md"), source: ".codemaxxing/CODEMAXXING.md" },
14
- { path: join(cwd, ".cursorrules"), source: ".cursorrules" },
15
- ];
16
-
17
- for (const { path, source } of candidates) {
18
- if (existsSync(path)) {
19
- try {
20
- const content = readFileSync(path, "utf-8").trim();
21
- if (content) return { content, source };
22
- } catch {
23
- // skip unreadable files
24
- }
25
- }
26
- }
27
- return null;
28
- }
29
-
30
- /**
31
- * Build a project context string by scanning the working directory
32
- */
33
- export async function buildProjectContext(cwd: string): Promise<string> {
34
- const lines: string[] = [];
35
- lines.push(`Project root: ${cwd}`);
36
-
37
- // Check for common project files
38
- const markers = [
39
- "package.json",
40
- "Cargo.toml",
41
- "pyproject.toml",
42
- "go.mod",
43
- "Makefile",
44
- "Dockerfile",
45
- "README.md",
46
- "CODEMAXXING.md",
47
- ];
48
-
49
- const found: string[] = [];
50
- for (const m of markers) {
51
- if (existsSync(join(cwd, m))) found.push(m);
52
- }
53
-
54
- if (found.length > 0) {
55
- lines.push(`Project files: ${found.join(", ")}`);
56
- }
57
-
58
- // Read package.json for project info
59
- const pkgPath = join(cwd, "package.json");
60
- if (existsSync(pkgPath)) {
61
- try {
62
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
63
- lines.push(`\nProject: ${pkg.name ?? "unknown"} v${pkg.version ?? "0.0.0"}`);
64
- if (pkg.description) lines.push(`Description: ${pkg.description}`);
65
- if (pkg.scripts) {
66
- lines.push(`Available scripts: ${Object.keys(pkg.scripts).join(", ")}`);
67
- }
68
- } catch {
69
- // ignore
70
- }
71
- }
72
-
73
- // Quick file tree (top level only)
74
- lines.push("\nProject structure:");
75
- const IGNORE = ["node_modules", ".git", "dist", ".next", "__pycache__", ".DS_Store"];
76
- try {
77
- const entries = readdirSync(cwd)
78
- .filter((e) => !IGNORE.includes(e))
79
- .slice(0, 30);
80
-
81
- for (const entry of entries) {
82
- const fullPath = join(cwd, entry);
83
- const stat = statSync(fullPath);
84
- if (stat.isDirectory()) {
85
- const count = readdirSync(fullPath).filter(
86
- (e) => !IGNORE.includes(e)
87
- ).length;
88
- lines.push(` 📁 ${entry}/ (${count} items)`);
89
- } else {
90
- lines.push(` 📄 ${entry}`);
91
- }
92
- }
93
- } catch {
94
- lines.push(" (could not read directory)");
95
- }
96
-
97
- // Build and append repo map
98
- try {
99
- const repoMap = await buildRepoMap(cwd);
100
- lines.push("\n" + repoMap);
101
- } catch (e) {
102
- // Repo map failed — continue without it
103
- lines.push("\n## Repository Map\n (unable to build map)");
104
- }
105
-
106
- return lines.join("\n");
107
- }
108
-
109
- /**
110
- * Get the system prompt for the coding agent
111
- */
112
- export async function getSystemPrompt(projectContext: string, skillPrompts: string = "", projectRules: string = ""): Promise<string> {
113
- const base = `You are CODEMAXXING, an AI coding assistant running in the terminal.
114
-
115
- You help developers understand, write, debug, and refactor code. You have access to tools that let you read files, write files, list directories, search code, and run shell commands.
116
-
117
- ## Rules
118
- - Always read relevant files before making changes
119
- - Explain what you're about to do before doing it
120
- - When writing files, show the user what will change
121
- - Be concise but thorough
122
- - If you're unsure, ask — don't guess
123
- - Use the run_command tool for building, testing, and linters
124
- - Never delete files without explicit confirmation
125
-
126
- ## Repository Map
127
- The project context below includes a map of the codebase structure. Use this map to understand what files, functions, classes, and types exist where. Use read_file to see full implementations when needed.
128
-
129
- ## Project Context
130
- ${projectContext}
131
-
132
- ## Behavior
133
- - Respond in markdown
134
- - Use code blocks with language tags
135
- - Be direct and helpful
136
- - If the user asks to "just do it", skip explanations and execute`;
137
-
138
- let prompt = base;
139
-
140
- if (projectRules) {
141
- prompt += "\n\n--- Project Rules (CODEMAXXING.md) ---\n" + projectRules + "\n--- End Project Rules ---";
142
- }
143
-
144
- if (skillPrompts) {
145
- prompt += "\n\n## Active Skills\n" + skillPrompts;
146
- }
147
-
148
- return prompt;
149
- }
150
-
151
- /**
152
- * Synchronous version for backwards compatibility (without repo map)
153
- * @deprecated Use async buildProjectContext instead
154
- */
155
- export function buildProjectContextSync(cwd: string): string {
156
- const lines: string[] = [];
157
- lines.push(`Project root: ${cwd}`);
158
-
159
- const markers = [
160
- "package.json", "Cargo.toml", "pyproject.toml", "go.mod",
161
- "Makefile", "Dockerfile", "README.md", "CODEMAXXING.md",
162
- ];
163
-
164
- const found: string[] = [];
165
- for (const m of markers) {
166
- if (existsSync(join(cwd, m))) found.push(m);
167
- }
168
-
169
- if (found.length > 0) {
170
- lines.push(`Project files: ${found.join(", ")}`);
171
- }
172
-
173
- return lines.join("\n");
174
- }
package/src/utils/git.ts DELETED
@@ -1,117 +0,0 @@
1
- import { execSync } from "child_process";
2
- import { existsSync } from "fs";
3
- import { join } from "path";
4
-
5
- /**
6
- * Check if a directory is inside a git repo
7
- */
8
- export function isGitRepo(cwd: string): boolean {
9
- try {
10
- execSync("git rev-parse --is-inside-work-tree", {
11
- cwd,
12
- stdio: "pipe",
13
- encoding: "utf-8",
14
- });
15
- return true;
16
- } catch {
17
- return false;
18
- }
19
- }
20
-
21
- /**
22
- * Get current branch name
23
- */
24
- export function getBranch(cwd: string): string {
25
- try {
26
- return execSync("git branch --show-current", {
27
- cwd,
28
- stdio: "pipe",
29
- encoding: "utf-8",
30
- }).trim();
31
- } catch {
32
- return "unknown";
33
- }
34
- }
35
-
36
- /**
37
- * Get short git status (clean / dirty + count)
38
- */
39
- export function getStatus(cwd: string): string {
40
- try {
41
- const output = execSync("git status --porcelain", {
42
- cwd,
43
- stdio: "pipe",
44
- encoding: "utf-8",
45
- }).trim();
46
- if (!output) return "clean";
47
- const count = output.split("\n").length;
48
- return `${count} changed`;
49
- } catch {
50
- return "unknown";
51
- }
52
- }
53
-
54
- /**
55
- * Auto-commit a file change with a descriptive message
56
- */
57
- export function autoCommit(cwd: string, filePath: string, action: string): boolean {
58
- try {
59
- execSync(`git add "${filePath}"`, { cwd, stdio: "pipe" });
60
- const msg = `codemaxxing: ${action} ${filePath}`;
61
- execSync(`git commit -m "${msg}" --no-verify`, { cwd, stdio: "pipe" });
62
- return true;
63
- } catch {
64
- return false;
65
- }
66
- }
67
-
68
- /**
69
- * Get diff of uncommitted changes (or last commit)
70
- */
71
- export function getDiff(cwd: string): string {
72
- try {
73
- // First try uncommitted changes
74
- let diff = execSync("git diff", { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
75
- // Include staged changes too
76
- const staged = execSync("git diff --cached", { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
77
- if (staged) diff = diff ? `${diff}\n${staged}` : staged;
78
-
79
- // If no uncommitted changes, show last commit
80
- if (!diff) {
81
- diff = execSync("git diff HEAD~1 HEAD", { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
82
- if (diff) return `(last commit)\n${diff}`;
83
- }
84
-
85
- return diff || "No changes.";
86
- } catch {
87
- return "Error getting diff.";
88
- }
89
- }
90
-
91
- /**
92
- * Undo the last codemaxxing commit
93
- */
94
- export function undoLastCommit(cwd: string): { success: boolean; message: string } {
95
- try {
96
- // Check if last commit was from codemaxxing
97
- const lastMsg = execSync("git log -1 --pretty=%s", {
98
- cwd,
99
- stdio: "pipe",
100
- encoding: "utf-8",
101
- }).trim();
102
-
103
- if (!lastMsg.startsWith("codemaxxing:")) {
104
- return {
105
- success: false,
106
- message: `Last commit is not from codemaxxing: "${lastMsg}"`,
107
- };
108
- }
109
-
110
- execSync("git reset --soft HEAD~1", { cwd, stdio: "pipe" });
111
- execSync("git restore --staged .", { cwd, stdio: "pipe" });
112
-
113
- return { success: true, message: `Reverted: ${lastMsg}` };
114
- } catch (e: any) {
115
- return { success: false, message: `Error: ${e.message}` };
116
- }
117
- }
@@ -1,131 +0,0 @@
1
- import os from "os";
2
- import { execSync } from "child_process";
3
-
4
- export interface HardwareInfo {
5
- cpu: { name: string; cores: number; speed: number };
6
- ram: number; // bytes
7
- gpu: { name: string; vram: number } | null; // vram in bytes, null if no GPU
8
- os: "macos" | "linux" | "windows";
9
- appleSilicon: boolean;
10
- }
11
-
12
- function getOS(): "macos" | "linux" | "windows" {
13
- switch (process.platform) {
14
- case "darwin": return "macos";
15
- case "win32": return "windows";
16
- default: return "linux";
17
- }
18
- }
19
-
20
- function getCPU(): { name: string; cores: number; speed: number } {
21
- const cpus = os.cpus();
22
- return {
23
- name: cpus[0]?.model?.trim() ?? "Unknown CPU",
24
- cores: cpus.length,
25
- speed: cpus[0]?.speed ?? 0, // MHz
26
- };
27
- }
28
-
29
- function getGPU(platform: "macos" | "linux" | "windows"): { name: string; vram: number } | null {
30
- try {
31
- if (platform === "macos") {
32
- const raw = execSync("system_profiler SPDisplaysDataType -json", {
33
- encoding: "utf-8",
34
- timeout: 5000,
35
- stdio: ["pipe", "pipe", "pipe"],
36
- });
37
- const data = JSON.parse(raw);
38
- const displays = data?.SPDisplaysDataType;
39
- if (Array.isArray(displays) && displays.length > 0) {
40
- const gpu = displays[0];
41
- const name: string = gpu.sppci_model ?? gpu._name ?? "Unknown GPU";
42
- // On Apple Silicon, VRAM is shared (unified memory) — report total RAM
43
- const vramStr: string = gpu["spdisplays_vram"] ?? gpu["spdisplays_vram_shared"] ?? "";
44
- let vram = 0;
45
- if (vramStr) {
46
- const match = vramStr.match(/(\d+)\s*(GB|MB)/i);
47
- if (match) {
48
- vram = parseInt(match[1]) * (match[2].toUpperCase() === "GB" ? 1024 * 1024 * 1024 : 1024 * 1024);
49
- }
50
- }
51
- // Apple Silicon unified memory — use total RAM as VRAM
52
- if (vram === 0 && name.toLowerCase().includes("apple")) {
53
- vram = os.totalmem();
54
- }
55
- return { name, vram };
56
- }
57
- }
58
-
59
- if (platform === "linux") {
60
- // Try NVIDIA first
61
- try {
62
- const raw = execSync("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader", {
63
- encoding: "utf-8",
64
- timeout: 5000,
65
- stdio: ["pipe", "pipe", "pipe"],
66
- });
67
- const line = raw.trim().split("\n")[0];
68
- if (line) {
69
- const parts = line.split(",").map(s => s.trim());
70
- const name = parts[0] ?? "NVIDIA GPU";
71
- const memMatch = (parts[1] ?? "").match(/(\d+)/);
72
- const vram = memMatch ? parseInt(memMatch[1]) * 1024 * 1024 : 0; // MiB to bytes
73
- return { name, vram };
74
- }
75
- } catch {
76
- // No NVIDIA, try lspci
77
- try {
78
- const raw = execSync("lspci | grep -i vga", {
79
- encoding: "utf-8",
80
- timeout: 5000,
81
- stdio: ["pipe", "pipe", "pipe"],
82
- });
83
- const line = raw.trim().split("\n")[0];
84
- if (line) {
85
- const name = line.split(":").slice(2).join(":").trim() || "Unknown GPU";
86
- return { name, vram: 0 };
87
- }
88
- } catch { /* no lspci */ }
89
- }
90
- }
91
-
92
- if (platform === "windows") {
93
- try {
94
- const raw = execSync("wmic path win32_VideoController get Name,AdapterRAM /format:csv", {
95
- encoding: "utf-8",
96
- timeout: 5000,
97
- stdio: ["pipe", "pipe", "pipe"],
98
- });
99
- const lines = raw.trim().split("\n").filter(l => l.trim() && !l.startsWith("Node"));
100
- if (lines.length > 0) {
101
- const parts = lines[0].split(",");
102
- const adapterRAM = parseInt(parts[1] ?? "0");
103
- const name = parts[2]?.trim() ?? "Unknown GPU";
104
- return { name, vram: isNaN(adapterRAM) ? 0 : adapterRAM };
105
- }
106
- } catch { /* no wmic */ }
107
- }
108
- } catch {
109
- // GPU detection failed
110
- }
111
- return null;
112
- }
113
-
114
- export function detectHardware(): HardwareInfo {
115
- const platform = getOS();
116
- const cpu = getCPU();
117
- const ram = os.totalmem();
118
- const gpu = getGPU(platform);
119
-
120
- // Detect Apple Silicon
121
- const appleSilicon = platform === "macos" && /apple\s+m/i.test(cpu.name);
122
-
123
- return { cpu, ram, gpu, os: platform, appleSilicon };
124
- }
125
-
126
- /** Format bytes to human-readable string */
127
- export function formatBytes(bytes: number): string {
128
- if (bytes >= 1024 * 1024 * 1024) return `${Math.round(bytes / (1024 * 1024 * 1024))} GB`;
129
- if (bytes >= 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))} MB`;
130
- return `${Math.round(bytes / 1024)} KB`;
131
- }
package/src/utils/lint.ts DELETED
@@ -1,116 +0,0 @@
1
- import { existsSync } from "fs";
2
- import { join, extname } from "path";
3
- import { execSync } from "child_process";
4
-
5
- interface LinterInfo {
6
- name: string;
7
- command: string;
8
- }
9
-
10
- /**
11
- * Detect the project linter based on config files in the working directory
12
- */
13
- export function detectLinter(cwd: string): LinterInfo | null {
14
- // JavaScript/TypeScript — check for biome first (faster), then eslint
15
- if (existsSync(join(cwd, "biome.json")) || existsSync(join(cwd, "biome.jsonc"))) {
16
- return { name: "Biome", command: "npx biome check" };
17
- }
18
- if (
19
- existsSync(join(cwd, ".eslintrc")) ||
20
- existsSync(join(cwd, ".eslintrc.js")) ||
21
- existsSync(join(cwd, ".eslintrc.cjs")) ||
22
- existsSync(join(cwd, ".eslintrc.json")) ||
23
- existsSync(join(cwd, ".eslintrc.yml")) ||
24
- existsSync(join(cwd, "eslint.config.js")) ||
25
- existsSync(join(cwd, "eslint.config.mjs")) ||
26
- existsSync(join(cwd, "eslint.config.ts"))
27
- ) {
28
- return { name: "ESLint", command: "npx eslint" };
29
- }
30
- // Check package.json for eslint dependency as fallback
31
- if (existsSync(join(cwd, "package.json"))) {
32
- try {
33
- const pkg = JSON.parse(require("fs").readFileSync(join(cwd, "package.json"), "utf-8"));
34
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
35
- if (allDeps["@biomejs/biome"]) {
36
- return { name: "Biome", command: "npx biome check" };
37
- }
38
- if (allDeps["eslint"]) {
39
- return { name: "ESLint", command: "npx eslint" };
40
- }
41
- } catch {
42
- // ignore
43
- }
44
- }
45
-
46
- // Python — ruff (fast) or flake8/pylint
47
- if (existsSync(join(cwd, "ruff.toml")) || existsSync(join(cwd, ".ruff.toml"))) {
48
- return { name: "Ruff", command: "ruff check" };
49
- }
50
- if (existsSync(join(cwd, "pyproject.toml"))) {
51
- try {
52
- const content = require("fs").readFileSync(join(cwd, "pyproject.toml"), "utf-8");
53
- if (content.includes("[tool.ruff]")) {
54
- return { name: "Ruff", command: "ruff check" };
55
- }
56
- } catch {
57
- // ignore
58
- }
59
- return { name: "Ruff", command: "ruff check" };
60
- }
61
-
62
- // Rust
63
- if (existsSync(join(cwd, "Cargo.toml"))) {
64
- return { name: "Clippy", command: "cargo clippy --message-format=short --" };
65
- }
66
-
67
- // Go
68
- if (existsSync(join(cwd, "go.mod"))) {
69
- return { name: "golangci-lint", command: "golangci-lint run" };
70
- }
71
-
72
- return null;
73
- }
74
-
75
- /**
76
- * Run the linter on a specific file and return errors (or null if clean)
77
- */
78
- export function runLinter(linter: LinterInfo, filePath: string, cwd: string): string | null {
79
- // Skip files that the linter can't handle
80
- const ext = extname(filePath).toLowerCase();
81
- const jsExts = new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts"]);
82
- const pyExts = new Set([".py", ".pyi"]);
83
- const rsExts = new Set([".rs"]);
84
- const goExts = new Set([".go"]);
85
-
86
- // Only lint files matching the linter's language
87
- if ((linter.name === "ESLint" || linter.name === "Biome") && !jsExts.has(ext)) return null;
88
- if (linter.name === "Ruff" && !pyExts.has(ext)) return null;
89
- if (linter.name === "Clippy" && !rsExts.has(ext)) return null;
90
- if (linter.name === "golangci-lint" && !goExts.has(ext)) return null;
91
-
92
- try {
93
- // Clippy works on the whole project, not individual files
94
- const command = linter.name === "Clippy"
95
- ? linter.command
96
- : `${linter.command} ${filePath}`;
97
-
98
- execSync(command, {
99
- cwd,
100
- encoding: "utf-8",
101
- timeout: 15000,
102
- stdio: ["pipe", "pipe", "pipe"],
103
- });
104
- return null; // No errors
105
- } catch (e: any) {
106
- const output = (e.stdout || "") + (e.stderr || "");
107
- const trimmed = output.trim();
108
- if (!trimmed) return null;
109
- // Limit output to avoid flooding context
110
- const lines = trimmed.split("\n");
111
- if (lines.length > 30) {
112
- return lines.slice(0, 30).join("\n") + `\n... (${lines.length - 30} more lines)`;
113
- }
114
- return trimmed;
115
- }
116
- }