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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mini-coder",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "A small, fast CLI coding agent",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
@@ -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) |