feinai 0.6.3 → 0.6.5
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 +182 -66
- package/package.json +1 -1
- package/src/cli.ts +5 -5
- package/src/dashboard.html +7 -1
- package/src/db.ts +2 -2
package/README.md
CHANGED
|
@@ -1,73 +1,134 @@
|
|
|
1
1
|
# feinai
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Local coordination layer for multi‑agent coding workflows.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
When multiple coding agents work on the same repo, things break long before the model runs out of IQ: duplicated work, inconsistent task state, agents trampling each other's branches, and no clear visibility into what is happening where.
|
|
6
6
|
|
|
7
|
-
feinai
|
|
7
|
+
**feinai** focuses on one thing: make that coordination deterministic, auditable, and safe for your git repo – locally, without a cloud service.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Why feinai
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Multi‑agent development breaks down without coordination infrastructure. Skills and prompts get agents started, but they do not solve the ugly parts of running several agents in parallel:
|
|
14
14
|
|
|
15
|
-
**
|
|
16
|
-
|
|
17
|
-
**No isolation.** Agents sharing a branch corrupt each other's work mid
|
|
18
|
-
|
|
19
|
-
**
|
|
20
|
-
|
|
21
|
-
**Skill-based approaches hit a ceiling.** Skills and prompt instructions are probabilistic — the model can ignore them, misinterpret them, or hallucinate state. Deterministic coordination requires a tool, not a suggestion. feinai makes the workflow atomic, auditable, and race-free at the infrastructure level.
|
|
15
|
+
- **Token waste on shared Markdown.** Agents reading `QUEUE.md` or `BACKLOG.md` to find their next task burn context on irrelevant state. A 200‑line plan file costs tokens every time – most of it noise for any given agent. feinai gives each agent exactly what it needs in a single call.
|
|
16
|
+
- **Inconsistent task state.** Two agents claim the same task. One overwrites the other's work. You find out when the merge fails. `feinai take` is an atomic SQL operation – if two agents race, one wins and one gets rejected. No duplicates, no silent overwrites.
|
|
17
|
+
- **No isolation in git.** Agents sharing a branch corrupt each other's work mid‑task. `feinai-dispatch` puts every agent in its own git worktree, linked to a specific task, visible in the dashboard. Work is isolated until it's ready to merge.
|
|
18
|
+
- **Zero visibility.** You don't know which agent is doing what, which files it touched, how long it has been running, or whether it's stuck. The feinai dashboard shows all of this live.
|
|
19
|
+
- **Skills hit a ceiling.** Skills and prompt instructions are probabilistic – the model can ignore them, misinterpret them, or hallucinate state. Deterministic coordination requires a tool, not a suggestion. feinai makes the workflow atomic, auditable, and race‑free at the infrastructure level.
|
|
22
20
|
|
|
23
21
|
---
|
|
24
22
|
|
|
25
23
|
## What feinai is
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
feinai is a **CLI + HTTP API + dashboard** that acts as the single source of truth for multi‑agent development workflows on a git repo.
|
|
26
|
+
|
|
27
|
+
It manages four core primitives:
|
|
28
|
+
|
|
29
|
+
- **Specs** – what to build and why.
|
|
30
|
+
- **Plans** – how to build it.
|
|
31
|
+
- **Tasks** – atomic units of work, with dependencies, quality gates, and worktree links.
|
|
32
|
+
- **Events** – append‑only audit log of every state change.
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
- **Plans** — how to build it
|
|
31
|
-
- **Tasks** — atomic units of work, with dependencies, quality gates, and worktree links
|
|
32
|
-
- **Dashboard** — live view of every agent, every worktree, every file being touched
|
|
34
|
+
Agents never read raw Markdown queues. They ask feinai for work:
|
|
33
35
|
|
|
34
|
-
```
|
|
36
|
+
```sh
|
|
35
37
|
feinai take TASK-121-A
|
|
36
38
|
# → {id, subject, description, workplan, packages, quality_gates, worktree, ...}
|
|
37
39
|
# One call. Everything the agent needs. Nothing it doesn't.
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
State lives in a local SQLite file. No cloud, no
|
|
42
|
+
State lives in a local SQLite file. No cloud, no external service, no account.
|
|
41
43
|
|
|
42
44
|
---
|
|
43
45
|
|
|
44
|
-
##
|
|
46
|
+
## Core concepts
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
- **Specs**
|
|
49
|
+
High‑level product requirements: why a feature exists and what "done" means. Specs link to plans and tasks.
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
+
- **Plans**
|
|
52
|
+
Versioned implementation plans for a spec. A plan explains how to build it – steps, trade‑offs, constraints.
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
- **Tasks**
|
|
55
|
+
Atomic units of work with:
|
|
56
|
+
- An ID (`TASK-001-A`)
|
|
57
|
+
- Subject and description
|
|
58
|
+
- Optional `blocked_by` dependencies
|
|
59
|
+
- `quality_gates` (commands/tests that must pass)
|
|
60
|
+
- A dedicated git worktree path
|
|
53
61
|
|
|
54
|
-
|
|
62
|
+
- **Events**
|
|
63
|
+
Append‑only log of everything that happens: `{parent_process}:{pid}:{user}`, timestamps, transitions. Every mutation to specs, plans, tasks or worktrees is recorded.
|
|
55
64
|
|
|
56
|
-
|
|
65
|
+
- **Worktrees**
|
|
66
|
+
Each task gets its own git worktree. Agents commit and push from there. The main branch stays clean until the work is ready to integrate.
|
|
57
67
|
|
|
58
|
-
|
|
68
|
+
---
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
## Runtime & footprint
|
|
71
|
+
|
|
72
|
+
- Implemented on top of **Bun 1.3+**.
|
|
73
|
+
- Installs two binaries:
|
|
74
|
+
- `feinai` – main CLI + embedded HTTP server and dashboard.
|
|
75
|
+
- `opengit` – safe git wrapper for parallel worktrees.
|
|
76
|
+
- Stores all state in a single SQLite file: `.tasca/tasca.db`, discovered by walking up from the current directory (like `.git`).
|
|
65
77
|
|
|
66
|
-
|
|
78
|
+
No background services are required beyond the optional dashboard server.
|
|
79
|
+
|
|
80
|
+
---
|
|
67
81
|
|
|
68
|
-
|
|
82
|
+
## Supply chain & safety
|
|
83
|
+
|
|
84
|
+
feinai is designed to be "boring" infrastructure:
|
|
85
|
+
|
|
86
|
+
- **Local‑only state.** All coordination lives in `.tasca/tasca.db` in your repo. There is no remote backend.
|
|
87
|
+
- **Explicit operations.** Every change to specs, plans, tasks and worktrees goes through the CLI or HTTP API and is logged in `events`.
|
|
88
|
+
- **Safe git workflow.** `feinai git` wraps git and blocks operations that can corrupt parallel worktrees (branch, checkout, merge, rebase, reset, fetch, pull, clone).
|
|
89
|
+
- **Auditability.** Every task has a clear chain: spec → plan → task → worktree → events. Every agent identity can be traced (`$FEINAI_USER` override supported).
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Using feinai with coding agents
|
|
94
|
+
|
|
95
|
+
feinai is built to sit **under** coding agents (Claude Code, pi‑style harnesses, etc.) as a coordination layer.
|
|
96
|
+
|
|
97
|
+
A typical pattern:
|
|
98
|
+
|
|
99
|
+
1. Human or design agent writes a spec and plan.
|
|
100
|
+
2. feinai decomposes the plan into tasks with dependencies and quality gates.
|
|
101
|
+
3. Worker agents:
|
|
102
|
+
- Call `feinai take` to claim a task atomically.
|
|
103
|
+
- Work in the dedicated worktree for that task.
|
|
104
|
+
- Run quality gates (tests, linters, typechecks).
|
|
105
|
+
- Mark the task as `done` or `fail` with a structured result.
|
|
106
|
+
4. A human (or integration agent) reviews and merges.
|
|
107
|
+
|
|
108
|
+
Agents don't parse `QUEUE.md`. They talk to a small local coordination service instead.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Claude Code skills
|
|
113
|
+
|
|
114
|
+
feinai ships five Claude Code skills covering the full development loop. They activate automatically when `.tasca/tasca.db` is present:
|
|
115
|
+
|
|
116
|
+
| Skill | Purpose |
|
|
117
|
+
|---------------------|--------------------------------------------------------|
|
|
118
|
+
| `feinai-sdd` | Teaches Claude the feinai workflow and concepts |
|
|
119
|
+
| `feinai-write-spec` | Writes spec + plan into feinai from a design thread |
|
|
120
|
+
| `feinai-write-tasks`| Decomposes a plan into atomic tasks with parallelism |
|
|
121
|
+
| `feinai-dispatch` | Orchestrates subagents in isolated git worktrees |
|
|
122
|
+
| `feinai-implement` | Claims and executes one task end‑to‑end |
|
|
123
|
+
|
|
124
|
+
Together they cover: design → spec → plan → tasks → parallel execution → merge.
|
|
125
|
+
|
|
126
|
+
### Activating skills in Claude Code
|
|
127
|
+
|
|
128
|
+
```sh
|
|
69
129
|
mkdir -p ~/.claude/skills
|
|
70
130
|
SKILLS=~/.bun/install/global/node_modules/feinai/skills
|
|
131
|
+
|
|
71
132
|
for skill in feinai-sdd feinai-write-spec feinai-write-tasks feinai-dispatch feinai-implement; do
|
|
72
133
|
ln -sf "$SKILLS/$skill" ~/.claude/skills/$skill
|
|
73
134
|
done
|
|
@@ -75,53 +136,79 @@ done
|
|
|
75
136
|
|
|
76
137
|
---
|
|
77
138
|
|
|
139
|
+
## Installation
|
|
140
|
+
|
|
141
|
+
Requires [Bun](https://bun.sh/) 1.3+.
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
bun install -g feinai
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This installs:
|
|
148
|
+
|
|
149
|
+
- `feinai`
|
|
150
|
+
- `opengit` (safe git wrapper for parallel worktrees)
|
|
151
|
+
|
|
152
|
+
### PATH setup (non‑interactive SSH)
|
|
153
|
+
|
|
154
|
+
In interactive shells and for local agents (Claude Code, opencode) it should work out of the box.
|
|
155
|
+
|
|
156
|
+
For non‑interactive SSH sessions (e.g. `ssh host 'feinai status'`), you may need a one‑time setup:
|
|
157
|
+
|
|
158
|
+
```sh
|
|
159
|
+
sudo ln -sf ~/.bun/bin/feinai /usr/local/bin/feinai
|
|
160
|
+
sudo ln -sf ~/.bun/bin/opengit /usr/local/bin/opengit
|
|
161
|
+
sudo ln -sf ~/.bun/bin/bun /usr/local/bin/bun
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
78
166
|
## Quick start
|
|
79
167
|
|
|
80
|
-
```
|
|
168
|
+
```sh
|
|
81
169
|
cd my-project
|
|
170
|
+
|
|
171
|
+
# Initialize local state
|
|
82
172
|
feinai init # creates .tasca/tasca.db, adds to .gitignore
|
|
83
173
|
|
|
174
|
+
# Add a spec and plan
|
|
84
175
|
feinai spec add SPEC-001 "User authentication" --content "..."
|
|
85
176
|
feinai plan add SPEC-001 --content "..."
|
|
86
|
-
feinai add TASK-001-A "Create auth schema" --spec SPEC-001 --gate "pnpm typecheck"
|
|
87
177
|
|
|
88
|
-
|
|
178
|
+
# Create a task with a quality gate
|
|
179
|
+
feinai add TASK-001-A "Create auth schema" \
|
|
180
|
+
--spec SPEC-001 \
|
|
181
|
+
--gate "pnpm typecheck"
|
|
182
|
+
|
|
183
|
+
# Agent claims a task (atomic)
|
|
184
|
+
feinai take TASK-001-A # returns full task payload as JSON
|
|
185
|
+
|
|
186
|
+
# Agent completes work
|
|
89
187
|
feinai done TASK-001-A --result "typecheck ✓"
|
|
90
188
|
|
|
189
|
+
# Start dashboard server
|
|
91
190
|
feinai server # live dashboard at http://127.0.0.1:8272
|
|
92
191
|
```
|
|
93
192
|
|
|
94
193
|
---
|
|
95
194
|
|
|
96
|
-
## Skills
|
|
97
|
-
|
|
98
|
-
feinai ships five Claude Code skills covering the full development lifecycle:
|
|
99
|
-
|
|
100
|
-
| Skill | Purpose |
|
|
101
|
-
|---|---|
|
|
102
|
-
| `feinai-sdd` | Activates when `.tasca/tasca.db` exists — teaches Claude the workflow |
|
|
103
|
-
| `feinai-write-spec` | Writes spec + plan into feinai from a design conversation |
|
|
104
|
-
| `feinai-write-tasks` | Decomposes plan into atomic tasks with parallelism analysis |
|
|
105
|
-
| `feinai-dispatch` | Orchestrates subagents in isolated git worktrees |
|
|
106
|
-
| `feinai-implement` | Claims and executes one task end-to-end |
|
|
107
|
-
|
|
108
|
-
Full lifecycle: design → spec → tasks → parallel execution → merge.
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
195
|
## Commands
|
|
113
196
|
|
|
114
|
-
|
|
197
|
+
High‑level CLI:
|
|
198
|
+
|
|
199
|
+
```text
|
|
115
200
|
feinai init Create .tasca/tasca.db
|
|
116
|
-
feinai status
|
|
201
|
+
feinai status Show counts: pending / in_progress / completed
|
|
117
202
|
feinai list [--pending] [--spec X] List tasks
|
|
118
203
|
feinai add ID "subject" Create task
|
|
119
204
|
feinai take ID Atomic claim — returns full task JSON
|
|
120
205
|
feinai done ID --result "..." Mark completed
|
|
121
206
|
feinai fail ID --error "..." Mark failed
|
|
122
207
|
feinai release ID Release back to pending
|
|
208
|
+
|
|
123
209
|
feinai spec add/list/show/done Spec lifecycle
|
|
124
210
|
feinai plan add/show Plan versions
|
|
211
|
+
|
|
125
212
|
feinai git <cmd> Safe git wrapper (blocks merge/rebase/checkout)
|
|
126
213
|
feinai server [--port N] [-d] Dashboard + REST API
|
|
127
214
|
```
|
|
@@ -130,34 +217,57 @@ feinai server [--port N] [-d] Dashboard + REST API
|
|
|
130
217
|
|
|
131
218
|
## Dashboard
|
|
132
219
|
|
|
133
|
-
|
|
220
|
+
Run:
|
|
221
|
+
|
|
222
|
+
```sh
|
|
134
223
|
feinai server -d # background, port 8272
|
|
135
224
|
feinai server --port 9000 # custom port
|
|
136
225
|
```
|
|
137
226
|
|
|
138
|
-
|
|
227
|
+
The dashboard shows per agent:
|
|
228
|
+
|
|
229
|
+
- Current task ID
|
|
230
|
+
- Worktree path and repo
|
|
231
|
+
- Files being modified
|
|
232
|
+
- Elapsed time
|
|
233
|
+
|
|
234
|
+
Active agents ripple in green, idle ones in gray. Updates stream in real time via SSE.
|
|
139
235
|
|
|
140
236
|
---
|
|
141
237
|
|
|
142
238
|
## `feinai git`
|
|
143
239
|
|
|
144
|
-
|
|
240
|
+
`feinai git` is a safety wrapper around git for parallel worktrees.
|
|
241
|
+
|
|
242
|
+
Allowed operations include:
|
|
145
243
|
|
|
146
|
-
```
|
|
244
|
+
```sh
|
|
147
245
|
feinai git worktree add .worktrees/TASK-001 origin/main
|
|
148
|
-
feinai git add .
|
|
246
|
+
feinai git add .
|
|
247
|
+
feinai git commit -m "feat: ..."
|
|
149
248
|
feinai git push origin HEAD:main
|
|
150
249
|
feinai git complete # sync main after push
|
|
151
250
|
```
|
|
152
251
|
|
|
153
|
-
|
|
252
|
+
The following are blocked when they would break the parallel workflow:
|
|
253
|
+
|
|
254
|
+
- `branch`
|
|
255
|
+
- `checkout`
|
|
256
|
+
- `merge`
|
|
257
|
+
- `rebase`
|
|
258
|
+
- `reset`
|
|
259
|
+
- `fetch`
|
|
260
|
+
- `pull`
|
|
261
|
+
- `clone`
|
|
262
|
+
|
|
263
|
+
Use your normal git tooling inside each worktree; use `feinai git` when operating on shared branches.
|
|
154
264
|
|
|
155
265
|
---
|
|
156
266
|
|
|
157
267
|
## Architecture
|
|
158
268
|
|
|
159
|
-
```
|
|
160
|
-
<project>/.tasca/tasca.db local SQLite
|
|
269
|
+
```text
|
|
270
|
+
<project>/.tasca/tasca.db # local SQLite database (discovered like .git)
|
|
161
271
|
|
|
162
272
|
specs — what to build
|
|
163
273
|
plans — how to build it (versioned)
|
|
@@ -165,10 +275,16 @@ tasks — atomic work units with blocked_by, quality_gates, worktree
|
|
|
165
275
|
events — append-only audit log: {parent_process}:{pid}:{user}
|
|
166
276
|
```
|
|
167
277
|
|
|
168
|
-
Every mutation is logged. Every agent is identified.
|
|
278
|
+
Every mutation is logged. Every agent is identified. You can override identity using:
|
|
279
|
+
|
|
280
|
+
```sh
|
|
281
|
+
export FEINAI_USER="ci-bot-01"
|
|
282
|
+
```
|
|
169
283
|
|
|
170
284
|
---
|
|
171
285
|
|
|
172
286
|
## License
|
|
173
287
|
|
|
174
|
-
MIT — built with ❤️ in Barcelona.
|
|
288
|
+
MIT — built with ❤️ in Barcelona.
|
|
289
|
+
|
|
290
|
+
"Feina" means "work" in Catalan. feinai is a tiny piece of infrastructure to keep that work coordinated.
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
type OutputFormat,
|
|
49
49
|
} from "./format";
|
|
50
50
|
|
|
51
|
-
const VERSION = "0.6.
|
|
51
|
+
const VERSION = "0.6.4";
|
|
52
52
|
|
|
53
53
|
interface ParsedArgs {
|
|
54
54
|
positional: string[];
|
|
@@ -396,20 +396,20 @@ function cmdInit(args: ParsedArgs): void {
|
|
|
396
396
|
const path = initDb();
|
|
397
397
|
console.log(`Initialized feinai DB at ${path}`);
|
|
398
398
|
|
|
399
|
-
// Auto-add .
|
|
399
|
+
// Auto-add .feinai/ to .gitignore if inside a git repo
|
|
400
400
|
if (existsSync(".git")) {
|
|
401
401
|
const gitignorePath = ".gitignore";
|
|
402
|
-
const entry = ".
|
|
402
|
+
const entry = ".feinai/";
|
|
403
403
|
|
|
404
404
|
if (!existsSync(gitignorePath)) {
|
|
405
405
|
writeFileSync(gitignorePath, entry + "\n");
|
|
406
|
-
console.log(".
|
|
406
|
+
console.log(".feinai/ added to .gitignore");
|
|
407
407
|
} else {
|
|
408
408
|
const content = readFileSync(gitignorePath, "utf-8");
|
|
409
409
|
if (!content.includes(entry)) {
|
|
410
410
|
const separator = content.endsWith("\n") ? "" : "\n";
|
|
411
411
|
writeFileSync(gitignorePath, content + separator + entry + "\n");
|
|
412
|
-
console.log(".
|
|
412
|
+
console.log(".feinai/ added to .gitignore");
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
415
|
}
|
package/src/dashboard.html
CHANGED
|
@@ -1158,6 +1158,9 @@
|
|
|
1158
1158
|
if (taskData.status === "completed" || taskData.status === "failed") {
|
|
1159
1159
|
actions.push(`<button class="btn" data-action="reopen" data-id="${escapeHtml(taskData.id)}">↩ reopen</button>`);
|
|
1160
1160
|
}
|
|
1161
|
+
if (taskData.spec_id) {
|
|
1162
|
+
actions.unshift(`<button class="btn" data-action="back-to-spec" data-spec="${escapeHtml(taskData.spec_id)}">← ${escapeHtml(taskData.spec_id)}</button>`);
|
|
1163
|
+
}
|
|
1161
1164
|
setModalBody(`
|
|
1162
1165
|
${actions.length ? `<div class="modal-actions">${actions.join("")}</div>` : ""}
|
|
1163
1166
|
<div class="modal-section">
|
|
@@ -1360,6 +1363,9 @@
|
|
|
1360
1363
|
await api("POST", `/api/tasks`, body);
|
|
1361
1364
|
toast("Task created", body.id);
|
|
1362
1365
|
closeModal();
|
|
1366
|
+
} else if (action === "back-to-spec") {
|
|
1367
|
+
const specId = btn.dataset.spec;
|
|
1368
|
+
if (specId) openSpecModal(specId);
|
|
1363
1369
|
}
|
|
1364
1370
|
} catch (err) {
|
|
1365
1371
|
toast("Error", err.message, true);
|
|
@@ -1463,7 +1469,7 @@
|
|
|
1463
1469
|
<div class="worktree-context">
|
|
1464
1470
|
<div class="context-row"><span class="context-label">Working directory</span><span class="context-value">${escapeHtml(workingDir)}</span></div>
|
|
1465
1471
|
<div class="context-row"><span class="context-label">Repo</span><span class="context-value">${escapeHtml(repoName)}</span></div>
|
|
1466
|
-
<div class="context-row"><span class="context-label">.
|
|
1472
|
+
<div class="context-row"><span class="context-label">.feinai</span><span class="context-value">${escapeHtml(tascaLoc)}</span></div>
|
|
1467
1473
|
</div>
|
|
1468
1474
|
<span class="elapsed-time" data-elapsed="${escapeHtml(task.taken_at ?? '')}"></span>
|
|
1469
1475
|
</div>
|
package/src/db.ts
CHANGED
|
@@ -183,7 +183,7 @@ function applySchema(db: DbInstance): void {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
/**
|
|
186
|
-
* Find .
|
|
186
|
+
* Find .feinai/feinai.db by walking up from cwd, like git does with .git.
|
|
187
187
|
* Returns null if no DB exists in the tree above the starting directory.
|
|
188
188
|
*/
|
|
189
189
|
export function findDbPath(startDir: string = process.cwd()): string | null {
|
|
@@ -200,7 +200,7 @@ export function findDbPath(startDir: string = process.cwd()): string | null {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
|
-
* Initialize a new
|
|
203
|
+
* Initialize a new feinai DB in the given directory (default: cwd).
|
|
204
204
|
* Returns the absolute path of the created DB file.
|
|
205
205
|
*/
|
|
206
206
|
export function initDb(dir: string = process.cwd()): string {
|