mini-coder 0.1.1 → 0.1.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.
- package/.claude/settings.local.json +43 -30
- package/README.md +1 -2
- package/dist/mc-edit.js +29 -5
- package/dist/mc.js +2672 -3244
- package/docs/mini-coder.1.md +4 -19
- package/lefthook.yml +15 -0
- package/package.json +3 -2
- package/research.md +0 -38
|
@@ -1,32 +1,45 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"WebSearch",
|
|
5
|
+
"WebFetch(domain:github.com)",
|
|
6
|
+
"WebFetch(domain:dev.to)",
|
|
7
|
+
"WebFetch(domain:mariozechner.at)",
|
|
8
|
+
"WebFetch(domain:lobste.rs)",
|
|
9
|
+
"WebFetch(domain:reading.sh)",
|
|
10
|
+
"WebFetch(domain:daveswift.com)",
|
|
11
|
+
"Bash(grep:*)",
|
|
12
|
+
"Bash(ls:*)",
|
|
13
|
+
"Bash(bun run:*)",
|
|
14
|
+
"Bash(git stash:*)",
|
|
15
|
+
"Bash(gh pr:*)",
|
|
16
|
+
"Bash(git status:*)",
|
|
17
|
+
"Bash(git add:*)",
|
|
18
|
+
"Bash(git commit:*)",
|
|
19
|
+
"Bash(sqlite3:*)",
|
|
20
|
+
"Bash(git branch:*)",
|
|
21
|
+
"Bash(git checkout:*)",
|
|
22
|
+
"Bash(npm info:*)",
|
|
23
|
+
"Bash(npm install:*)",
|
|
24
|
+
"Bash(find:*)",
|
|
25
|
+
"Bash(git log:*)",
|
|
26
|
+
"Bash(npm ls:*)",
|
|
27
|
+
"Bash(gh api:*)",
|
|
28
|
+
"Bash(bun:*)",
|
|
29
|
+
"Bash(npx tsc:*)",
|
|
30
|
+
"WebFetch(domain:docs.anthropic.com)",
|
|
31
|
+
"WebFetch(domain:sdk.vercel.ai)",
|
|
32
|
+
"WebFetch(domain:ai-sdk.dev)",
|
|
33
|
+
"WebFetch(domain:www.npmjs.com)",
|
|
34
|
+
"Bash(curl -sL https://registry.npmjs.org/opencode-anthropic-auth/-/opencode-anthropic-auth-0.0.13.tgz)",
|
|
35
|
+
"Bash(tar xz:*)",
|
|
36
|
+
"Bash(tmux new-session:*)",
|
|
37
|
+
"Bash(tmux capture-pane:*)",
|
|
38
|
+
"Bash(tmux list-sessions:*)",
|
|
39
|
+
"Bash(tmux kill-session:*)",
|
|
40
|
+
"Bash(python3:*)",
|
|
41
|
+
"Bash(echo \"EXIT: $?\")",
|
|
42
|
+
"Bash(xargs cat:*)"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
32
45
|
}
|
package/README.md
CHANGED
|
@@ -53,11 +53,10 @@ Use `/login` inside the REPL to authenticate via browser-based OAuth (currently
|
|
|
53
53
|
- **Multi-provider** — auto-discovers Anthropic, OpenAI, Gemini, Ollama, or any OpenAI-compatible endpoint
|
|
54
54
|
- **Session memory** — SQLite-backed. Resume with `-c` or `-r <id>`
|
|
55
55
|
- **Shell integration** — `!` prefix for inline commands, `@` to reference files with tab completion
|
|
56
|
-
- **Subagents** — spawn parallel mini-coder instances for independent subtasks
|
|
57
56
|
- **Web search** — `webSearch` + `webContent` tools when `EXA_API_KEY` is set
|
|
58
57
|
- **MCP support** — connect external tool servers over HTTP or stdio
|
|
59
58
|
- **Custom commands** — drop `.md` files in `.agents/commands/` → instant `/slash` commands
|
|
60
|
-
- **Custom agents** — `.agents/agents/*.md` for specialized personas
|
|
59
|
+
- **Custom agents** — `.agents/agents/*.md` for specialized personas you can activate with `/agent`
|
|
61
60
|
- **Skills** — `.agents/skills/<name>/SKILL.md`, inject with `@name`
|
|
62
61
|
- **`mc-edit`** — safe, exact-text file editing (no full-file rewrites)
|
|
63
62
|
- **16 ANSI colors** — inherits your terminal theme. Always looks right.
|
package/dist/mc-edit.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// src/cli/structured-output.ts
|
|
5
5
|
import { createTwoFilesPatch } from "diff";
|
|
6
|
+
import * as c from "yoctocolors";
|
|
6
7
|
function normalizePatchLines(patchText) {
|
|
7
8
|
const patchLines = patchText.split(`
|
|
8
9
|
`);
|
|
@@ -17,14 +18,30 @@ function normalizePatchLines(patchText) {
|
|
|
17
18
|
return line;
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
|
-
function
|
|
21
|
+
function colorizeDiffLine(line) {
|
|
22
|
+
if (line.startsWith("---") || line.startsWith("+++"))
|
|
23
|
+
return c.dim(line);
|
|
24
|
+
if (line.startsWith("@@"))
|
|
25
|
+
return c.cyan(line);
|
|
26
|
+
if (line.startsWith("+"))
|
|
27
|
+
return c.green(line);
|
|
28
|
+
if (line.startsWith("-"))
|
|
29
|
+
return c.red(line);
|
|
30
|
+
return line;
|
|
31
|
+
}
|
|
32
|
+
function renderUnifiedDiff(filePath, before, after, options) {
|
|
21
33
|
if (before === after) {
|
|
22
34
|
return "(no changes)";
|
|
23
35
|
}
|
|
24
36
|
const patchText = createTwoFilesPatch(filePath, filePath, before, after, "", "", {
|
|
25
37
|
context: 3
|
|
26
38
|
});
|
|
27
|
-
|
|
39
|
+
const lines = normalizePatchLines(patchText);
|
|
40
|
+
if (options?.colorize) {
|
|
41
|
+
return lines.map(colorizeDiffLine).join(`
|
|
42
|
+
`);
|
|
43
|
+
}
|
|
44
|
+
return lines.join(`
|
|
28
45
|
`);
|
|
29
46
|
}
|
|
30
47
|
function renderMetadataBlock(result) {
|
|
@@ -43,8 +60,11 @@ function renderMetadataBlock(result) {
|
|
|
43
60
|
}
|
|
44
61
|
function writeFileEditResult(io, result) {
|
|
45
62
|
if (result.ok) {
|
|
63
|
+
const colorize = process.env.FORCE_COLOR === "1" || process.env.FORCE_COLOR === "true";
|
|
46
64
|
const sections = [
|
|
47
|
-
renderUnifiedDiff(result.path, result.before, result.after
|
|
65
|
+
renderUnifiedDiff(result.path, result.before, result.after, {
|
|
66
|
+
colorize
|
|
67
|
+
}),
|
|
48
68
|
renderMetadataBlock(result)
|
|
49
69
|
];
|
|
50
70
|
io.stdout(`${sections.join(`
|
|
@@ -64,7 +84,7 @@ function stripMatchingQuotes(value) {
|
|
|
64
84
|
if (value.length < 2)
|
|
65
85
|
return value;
|
|
66
86
|
const first = value[0];
|
|
67
|
-
const last = value
|
|
87
|
+
const last = value.at(-1);
|
|
68
88
|
if ((first === '"' || first === "'") && first === last) {
|
|
69
89
|
return value.slice(1, -1);
|
|
70
90
|
}
|
|
@@ -76,7 +96,11 @@ function normalizePathInput(pathInput) {
|
|
|
76
96
|
function resolvePath(cwdInput, pathInput) {
|
|
77
97
|
const cwd = cwdInput ?? process.cwd();
|
|
78
98
|
const normalizedInput = normalizePathInput(pathInput);
|
|
79
|
-
|
|
99
|
+
let expanded = normalizedInput;
|
|
100
|
+
if (normalizedInput.startsWith("~/"))
|
|
101
|
+
expanded = join(homedir(), normalizedInput.slice(2));
|
|
102
|
+
else if (normalizedInput === "~")
|
|
103
|
+
expanded = homedir();
|
|
80
104
|
const filePath = expanded.startsWith("/") ? expanded : join(cwd, expanded);
|
|
81
105
|
const relPath = relative(cwd, filePath);
|
|
82
106
|
return { cwd, filePath, relPath };
|