mini-coder 0.0.5 → 0.0.6
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/README.md +8 -0
- package/better-errors.md +96 -0
- package/dist/mc.js +292 -261
- package/docs/configs.md +77 -0
- package/docs/tool-hooks.md +142 -0
- package/package.json +1 -1
- package/code-quality-issues.md +0 -135
package/docs/configs.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Config conventions
|
|
2
|
+
|
|
3
|
+
mini-coder supports both its native `.agents` convention and Claude Code's `.claude` convention for commands and skills.
|
|
4
|
+
|
|
5
|
+
## Supported config roots
|
|
6
|
+
|
|
7
|
+
| Root | Purpose |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `.agents/` | mini-coder native config |
|
|
10
|
+
| `.claude/` | Claude Code-compatible commands/skills |
|
|
11
|
+
|
|
12
|
+
Each root can exist in:
|
|
13
|
+
|
|
14
|
+
- **Local (repo):** `./.agents`, `./.claude`
|
|
15
|
+
- **Global (home):** `~/.agents`, `~/.claude`
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
Supported locations:
|
|
20
|
+
|
|
21
|
+
- `./.agents/commands/*.md`
|
|
22
|
+
- `~/.agents/commands/*.md`
|
|
23
|
+
- `./.claude/commands/*.md`
|
|
24
|
+
- `~/.claude/commands/*.md`
|
|
25
|
+
|
|
26
|
+
Format:
|
|
27
|
+
|
|
28
|
+
```md
|
|
29
|
+
---
|
|
30
|
+
description: Optional help text
|
|
31
|
+
model: optional/model-override
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
Prompt template body with $ARGUMENTS and $1..$9 support.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Filename becomes the command name (`review.md` => `/review`).
|
|
38
|
+
|
|
39
|
+
## Skills
|
|
40
|
+
|
|
41
|
+
Supported locations:
|
|
42
|
+
|
|
43
|
+
- `./.agents/skills/<skill-name>/SKILL.md`
|
|
44
|
+
- `~/.agents/skills/<skill-name>/SKILL.md`
|
|
45
|
+
- `./.claude/skills/<skill-name>/SKILL.md`
|
|
46
|
+
- `~/.claude/skills/<skill-name>/SKILL.md`
|
|
47
|
+
|
|
48
|
+
Format:
|
|
49
|
+
|
|
50
|
+
```md
|
|
51
|
+
---
|
|
52
|
+
name: optional-skill-name
|
|
53
|
+
description: Optional help text
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
Skill instructions/content.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If `name` is omitted, folder name is used.
|
|
60
|
+
|
|
61
|
+
## Agents (mini-coder specific)
|
|
62
|
+
|
|
63
|
+
Custom subagents are configured in `.agents`:
|
|
64
|
+
|
|
65
|
+
- `./.agents/agents/*.md`
|
|
66
|
+
- `~/.agents/agents/*.md`
|
|
67
|
+
|
|
68
|
+
(There is no `.claude` compatibility path for agents.)
|
|
69
|
+
|
|
70
|
+
## Precedence and conflicts
|
|
71
|
+
|
|
72
|
+
Precedence rules:
|
|
73
|
+
|
|
74
|
+
1. **Local overrides global**
|
|
75
|
+
2. At the **same scope** (both local or both global), if `.agents` and `.claude` define the same command/skill name, **`.agents` wins**
|
|
76
|
+
|
|
77
|
+
When same-scope conflicts are detected for commands/skills, mini-coder prints a warning and uses the `.agents` version.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Tool Hooks
|
|
2
|
+
|
|
3
|
+
A tool hook is an executable script that runs automatically after a specific tool call succeeds. Use hooks to trigger side effects — linting, formatting, logging, notifications — without modifying the agent's behaviour.
|
|
4
|
+
|
|
5
|
+
> Hooks fire **after** the tool succeeds. Failures are silently swallowed and never crash the agent.
|
|
6
|
+
|
|
7
|
+
## Where to put them
|
|
8
|
+
|
|
9
|
+
Hooks live in a `hooks/` folder inside an `.agents` config root:
|
|
10
|
+
|
|
11
|
+
| Location | Scope |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `.agents/hooks/post-<tool>` | Current repo only |
|
|
14
|
+
| `~/.agents/hooks/post-<tool>` | All projects (global) |
|
|
15
|
+
|
|
16
|
+
Local hooks take precedence over global ones. The filename must match `post-<tool>` exactly — no extension.
|
|
17
|
+
|
|
18
|
+
## Supported tools
|
|
19
|
+
|
|
20
|
+
| Tool | Hook filename |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `glob` | `post-glob` |
|
|
23
|
+
| `grep` | `post-grep` |
|
|
24
|
+
| `read` | `post-read` |
|
|
25
|
+
| `create` | `post-create` |
|
|
26
|
+
| `replace` | `post-replace` |
|
|
27
|
+
| `insert` | `post-insert` |
|
|
28
|
+
| `shell` | `post-shell` |
|
|
29
|
+
|
|
30
|
+
MCP tools are not hookable.
|
|
31
|
+
|
|
32
|
+
## Script requirements
|
|
33
|
+
|
|
34
|
+
The script must be executable (`chmod +x`). It can be written in any language — bash, Python, Node, etc. It receives context via environment variables and its exit code is reported in the UI (zero = success, non-zero = failure).
|
|
35
|
+
|
|
36
|
+
## Environment variables
|
|
37
|
+
|
|
38
|
+
All hooks receive:
|
|
39
|
+
|
|
40
|
+
| Variable | Description |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `TOOL` | Name of the tool that fired |
|
|
43
|
+
| `CWD` | Working directory of the session |
|
|
44
|
+
|
|
45
|
+
Plus tool-specific variables:
|
|
46
|
+
|
|
47
|
+
### `post-create`
|
|
48
|
+
|
|
49
|
+
| Variable | Description |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `FILEPATH` | Absolute path of the file written |
|
|
52
|
+
| `DIFF` | Unified diff of the change |
|
|
53
|
+
| `CREATED` | `true` if the file was newly created, `false` if overwritten |
|
|
54
|
+
|
|
55
|
+
### `post-replace`
|
|
56
|
+
|
|
57
|
+
| Variable | Description |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `FILEPATH` | Absolute path of the file modified |
|
|
60
|
+
| `DIFF` | Unified diff of the change |
|
|
61
|
+
| `DELETED` | `true` if lines were deleted (no replacement content), `false` otherwise |
|
|
62
|
+
|
|
63
|
+
### `post-insert`
|
|
64
|
+
|
|
65
|
+
| Variable | Description |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `FILEPATH` | Absolute path of the file modified |
|
|
68
|
+
| `DIFF` | Unified diff of the change |
|
|
69
|
+
|
|
70
|
+
### `post-shell`
|
|
71
|
+
|
|
72
|
+
| Variable | Description |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `COMMAND` | The shell command that was run |
|
|
75
|
+
| `EXIT_CODE` | Exit code of the command |
|
|
76
|
+
| `TIMED_OUT` | `true` if the command timed out |
|
|
77
|
+
| `STDOUT` | Captured standard output |
|
|
78
|
+
| `STDERR` | Captured standard error |
|
|
79
|
+
|
|
80
|
+
### `post-glob`
|
|
81
|
+
|
|
82
|
+
| Variable | Description |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `PATTERN` | The glob pattern that was searched |
|
|
85
|
+
|
|
86
|
+
### `post-grep`
|
|
87
|
+
|
|
88
|
+
| Variable | Description |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `PATTERN` | The regex pattern that was searched |
|
|
91
|
+
|
|
92
|
+
### `post-read`
|
|
93
|
+
|
|
94
|
+
| Variable | Description |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `FILEPATH` | Absolute path of the file read |
|
|
97
|
+
|
|
98
|
+
## Examples
|
|
99
|
+
|
|
100
|
+
### Auto-format on write
|
|
101
|
+
|
|
102
|
+
`.agents/hooks/post-create`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
#!/usr/bin/env bash
|
|
106
|
+
# Run the project formatter whenever the agent creates or overwrites a file.
|
|
107
|
+
bun run format -- "$FILEPATH"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
chmod +x .agents/hooks/post-create
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Pair with a matching `post-replace` and `post-insert` to cover all write tools.
|
|
115
|
+
|
|
116
|
+
### Log every shell command
|
|
117
|
+
|
|
118
|
+
`~/.agents/hooks/post-shell`:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
#!/usr/bin/env bash
|
|
122
|
+
# Append a record of every shell command to a global audit log.
|
|
123
|
+
echo "$(date -u +%FT%TZ) exit=$EXIT_CODE $COMMAND" >> ~/.config/mini-coder/shell-audit.log
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
chmod +x ~/.agents/hooks/post-shell
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Notify on file write
|
|
131
|
+
|
|
132
|
+
`.agents/hooks/post-replace`:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
#!/usr/bin/env bash
|
|
136
|
+
# macOS notification when the agent edits a file.
|
|
137
|
+
osascript -e "display notification \"$FILEPATH\" with title \"mini-coder wrote a file\""
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Hook lookup
|
|
141
|
+
|
|
142
|
+
Hooks are resolved once at session start and cached in memory — there is no filesystem access per tool call. Changing a hook script takes effect on the next session.
|
package/package.json
CHANGED
package/code-quality-issues.md
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# Code Quality Issues
|
|
2
|
-
|
|
3
|
-
## 1. 🔴 Duplicate Code — `parseFrontmatter` tripled across modules
|
|
4
|
-
|
|
5
|
-
`parseFrontmatter` (including its `Frontmatter` interface, `FM_RE` regex and YAML key-parsing loop) is **copy-pasted verbatim** in three files:
|
|
6
|
-
|
|
7
|
-
- `src/cli/agents.ts` (lines 20–45)
|
|
8
|
-
- `src/cli/custom-commands.ts` (lines 20–45)
|
|
9
|
-
- `src/cli/skills.ts` has a partial version `parseSkillMeta` that reads `name` and `description` from the same format.
|
|
10
|
-
|
|
11
|
-
The agents and custom-commands versions are byte-for-byte identical — same regex, same loop, same trim/strip-quotes, same `description`/`model` key handling. The only difference is the struct they populate. Fix: extract into a shared `src/cli/frontmatter.ts` utility and import it in all three.
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 2. 🔴 Duplicate Code — `loadFromDir` pattern tripled
|
|
16
|
-
|
|
17
|
-
The `loadFromDir` function in `agents.ts` and `custom-commands.ts` is essentially the same skeleton: `existsSync` check → `readdirSync` → `.endsWith(".md")` filter → `readFileSync` → `parseFrontmatter` → `Map.set`. The `loadSkills` version differs only in that it looks for `SKILL.md` inside subdirectories instead of `.md` flat files, but the rest of the structure is the same. Same for the public `loadXxx(cwd)` function: three identical "merge global + local, local wins" patterns.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 3. 🔴 Duplicate Code — `homedir()`-based `cwdDisplay` computed in two places in `agent.ts`
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
|
-
// buildSystemPrompt (line 98-100)
|
|
25
|
-
const cwdDisplay = cwd.startsWith(homedir())
|
|
26
|
-
? `~${cwd.slice(homedir().length)}`
|
|
27
|
-
: cwd;
|
|
28
|
-
|
|
29
|
-
// renderStatusBarForSession (line 646-648)
|
|
30
|
-
const cwdDisplay = cwd.startsWith(homedir())
|
|
31
|
-
? `~${cwd.slice(homedir().length)}`
|
|
32
|
-
: cwd;
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Also duplicated in `session/manager.ts` (line 53–55) and `cli/output.ts` already has `HOME = homedir()` cached at the top. This pattern should be a small helper function, e.g. `tildePath(p: string): string`.
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## 4. 🔴 Inlined `import()` calls — violates project rule
|
|
40
|
-
|
|
41
|
-
The rule says **"Do not inline `import` calls"**. There are 12 occurrences of dynamic inline type imports:
|
|
42
|
-
|
|
43
|
-
- `src/agent/agent.ts` lines 197, 224, 673 — `import("../tools/subagent.ts").SubagentOutput`, `SubagentToolEntry`, `CoreMessage`
|
|
44
|
-
- `src/agent/tools.ts` line 104 — `import("../tools/subagent.ts").SubagentOutput`
|
|
45
|
-
- `src/cli/commands.ts` line 44 — `import("../tools/subagent.ts").SubagentOutput`
|
|
46
|
-
- `src/cli/output.ts` lines 332, 342, 512, 579, 597 — `SubagentToolEntry`, `SubagentOutput`, `CoreMessage`
|
|
47
|
-
- `src/llm-api/types.ts` line 81 — `import("../llm-api/turn.ts").CoreMessage`
|
|
48
|
-
- `src/llm-api/turn.ts` line 32 — `import("ai").FlexibleSchema<unknown>`
|
|
49
|
-
|
|
50
|
-
All of these should be top-level `import type` statements.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## 5. 🟡 Dead code — `userMessage` in `turn.ts` is never called
|
|
55
|
-
|
|
56
|
-
`src/llm-api/turn.ts` line 185 exports `userMessage(text: string): CoreMessage`. It is never imported or called anywhere in the codebase. It should be removed.
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## 6. 🟡 Dead code — `availableProviders` imported but never used
|
|
61
|
-
|
|
62
|
-
`src/cli/commands.ts` imports `availableProviders` from `providers.ts` (line 3) but it is never referenced anywhere in that file (only `fetchAvailableModels` is used). This is an unused import.
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## 7. 🟡 Dead code — `saveMessage` (singular) exported but never used
|
|
67
|
-
|
|
68
|
-
`src/session/db.ts` exports `saveMessage` (single-message variant, line 191). The entire codebase always calls `saveMessages` (plural). `saveMessage` has no callers and should be removed.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## 8. 🟡 Dead code — `updateSessionTitle` and `deleteSession` exported but never called
|
|
73
|
-
|
|
74
|
-
`src/session/db.ts` exports `updateSessionTitle` (line 161) and `deleteSession` (line 185). Neither appears in any other file. They may be future API surface, but currently they are dead exports.
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## 9. 🟡 Dead code — most of `src/llm-api/types.ts` is orphaned
|
|
79
|
-
|
|
80
|
-
`ProviderConfig`, `MessageRole`, `TextContent`, `ToolCallContent`, `ToolResultContent`, `MessageContent`, and `Message` are all defined and exported in `types.ts` but **never imported anywhere**. The codebase uses `CoreMessage` from `turn.ts` directly for all message handling. The only things from `types.ts` that are actually used are `ToolDef` and the `TurnEvent` family. The unused types should be removed.
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## 10. 🟡 Unused import — `relative` in `session/manager.ts`
|
|
85
|
-
|
|
86
|
-
`src/session/manager.ts` line 2 imports `relative` from `"node:path"` but it is never used anywhere in the file.
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## 11. 🟡 Unused import — `PREFIX` in `session/manager.ts`
|
|
91
|
-
|
|
92
|
-
`src/session/manager.ts` line 4 imports `PREFIX` from `"../cli/output.ts"` but it is not used anywhere in the file (only `writeln` and `c` from `yoctocolors` are used in `printSessionList`).
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## 12. 🟡 Bug-prone — `zenGoogle` ignores its parameter and recreates provider on each call
|
|
97
|
-
|
|
98
|
-
`providers.ts` line 78: `zenGoogle(modelId: string)` takes `modelId` but only uses it to pass to `createGoogleGenerativeAI` (which doesn't use it — the model ID is passed to the returned function). Also unlike the other zen providers, `zenGoogle` doesn't memoize — it creates a new `createGoogleGenerativeAI` instance on every call. This is inconsistent and wasteful.
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## 13. 🟡 Minor — double `homedir()` call per `cwdDisplay` computation
|
|
103
|
-
|
|
104
|
-
In `buildSystemPrompt` and `renderStatusBarForSession` (agent.ts), `homedir()` is called twice inline:
|
|
105
|
-
```ts
|
|
106
|
-
cwd.startsWith(homedir()) ? `~${cwd.slice(homedir().length)}` : cwd
|
|
107
|
-
```
|
|
108
|
-
`homedir()` is cheap but its result is constant — it should be captured once (as `output.ts` already does with `const HOME = homedir()`).
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## 14. 🟢 Style — `eslint-disable` comments in `mcp/client.ts`
|
|
113
|
-
|
|
114
|
-
Lines 81 and 88 in `mcp/client.ts` contain `// eslint-disable-next-line @typescript-eslint/no-explicit-any` comments. The project uses Biome, not ESLint — these comments are dead noise and have no effect. They should be removed.
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## Summary
|
|
119
|
-
|
|
120
|
-
| # | Severity | File(s) | Issue |
|
|
121
|
-
|---|---|---|---|
|
|
122
|
-
| 1 | 🔴 | `agents.ts`, `custom-commands.ts`, `skills.ts` | `parseFrontmatter` duplicated 3× |
|
|
123
|
-
| 2 | 🔴 | same 3 files | `loadFromDir` + merge pattern duplicated 3× |
|
|
124
|
-
| 3 | 🔴 | `agent.ts` (×2), `manager.ts` | `cwdDisplay` tilde logic duplicated |
|
|
125
|
-
| 4 | 🔴 | 6 files (12 occurrences) | Inlined `import()` type calls — project rule violation |
|
|
126
|
-
| 5 | 🟡 | `turn.ts` | `userMessage` exported but never used |
|
|
127
|
-
| 6 | 🟡 | `commands.ts` | `availableProviders` imported but never used |
|
|
128
|
-
| 7 | 🟡 | `db.ts` | `saveMessage` (singular) exported but never called |
|
|
129
|
-
| 8 | 🟡 | `db.ts` | `updateSessionTitle`, `deleteSession` — dead exports |
|
|
130
|
-
| 9 | 🟡 | `types.ts` | `ProviderConfig`, `Message`, `MessageRole`, etc. — never imported |
|
|
131
|
-
| 10 | 🟡 | `manager.ts` | `relative` imported but not used |
|
|
132
|
-
| 11 | 🟡 | `manager.ts` | `PREFIX` imported but not used |
|
|
133
|
-
| 12 | 🟡 | `providers.ts` | `zenGoogle` doesn't memoize, ignores its parameter |
|
|
134
|
-
| 13 | 🟡 | `agent.ts` | `homedir()` called twice per expression |
|
|
135
|
-
| 14 | 🟢 | `mcp/client.ts` | Dead `eslint-disable` comments (project uses Biome) |
|