obsidian-lean-coder 0.1.0 → 0.2.0
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/CHANGELOG.md +30 -1
- package/README.md +39 -13
- package/bin/olc-setup.js +128 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +10 -1
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to OLC (Obsidian Lean Coder) are recorded here.
|
|
4
4
|
OLC is pre-release: versions are `0.x` until a controlled-testing release says otherwise.
|
|
5
|
-
`package.json`
|
|
5
|
+
`package.json` shipped `"private": true` through 0.1.0; the flag was removed at publish time with explicit user approval, and 0.1.0 is live as [`obsidian-lean-coder`](https://www.npmjs.com/package/obsidian-lean-coder). Publishing a new version is still a separate explicitly approved action, never automatic.
|
|
6
|
+
|
|
7
|
+
## [0.2.0] — 2026-10-13 — `olc-setup` resource installer
|
|
8
|
+
|
|
9
|
+
New `olc-setup setup [--project|--global]` command (run manually via `npx obsidian-lean-coder setup`
|
|
10
|
+
after install): copies the shipped agents/skills into OpenCode discovery paths —
|
|
11
|
+
`<cwd>/.opencode` (project, default) or `~/.config/opencode` (`$XDG_CONFIG_HOME/opencode` when set,
|
|
12
|
+
global; global use is allowed only for this plugin's own install). Missing directories are created;
|
|
13
|
+
existing OLC agent/skill files are overwritten with the package versions (a deliberate, narrow
|
|
14
|
+
exception to the create-only rule, scoped to the files this command owns — see README §2).
|
|
15
|
+
`--dry-run` previews without writing; `opencode.json` is never edited (manual snippet printed after
|
|
16
|
+
each run). Node builtins only, no runtime dependencies.
|
|
17
|
+
|
|
18
|
+
- **Verification:** 6 fixture tests (`tests/setup.test.ts`: create, skip/overwrite, dry-run,
|
|
19
|
+
global scope, usage errors, mkdir -p); full suite 146/146 pass; typecheck/build clean.
|
|
20
|
+
- **Upgrade:** `npm install obsidian-lean-coder@0.2.0`, then `npx obsidian-lean-coder setup`
|
|
21
|
+
(add `--global` for global scope).
|
|
22
|
+
|
|
23
|
+
## [0.1.1] — 2026-10-13 — plugin entrypoint fix
|
|
24
|
+
|
|
25
|
+
Fixes npm-package activation (reported: `npm install` worked but nothing appeared in OpenCode).
|
|
26
|
+
The package-root entrypoint `dist/index.js` exported only `OLC_VERSION`, so npm loaders —
|
|
27
|
+
which resolve the package root — never saw the plugin default export and ignored the package.
|
|
28
|
+
`src/index.ts` now re-exports the plugin default alongside `OLC_VERSION`.
|
|
29
|
+
Agents/skills still appear only via the project-local `.opencode` copy (by design, OLC-012).
|
|
30
|
+
|
|
31
|
+
- **Verification:** typecheck clean, build OK, mock-ctx plugin load (`id=olc`, correct payload),
|
|
32
|
+
full suite 140/140 pass, real-loader test (`loading plugin`, zero `failed to load plugin`).
|
|
33
|
+
- **Upgrade:** `npm install obsidian-lean-coder@0.1.1`, then list the package in `opencode.json`
|
|
34
|
+
`plugins` (see README §2).
|
|
6
35
|
|
|
7
36
|
## [0.1.0] — 2026-10-13 — MVP pre-release
|
|
8
37
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OLC — Obsidian Lean Coder
|
|
2
2
|
|
|
3
|
-
OpenCode extension for project-scoped planning, memory, and safe Git checkpoints.
|
|
3
|
+
OpenCode extension for project-scoped planning, memory, and safe Git checkpoints. On npm as `obsidian-lean-coder` (v0.1.1 fixes plugin activation — see CHANGELOG).
|
|
4
4
|
|
|
5
5
|
## Three separate steps
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ Do not confuse these. They are different operations with different commands:
|
|
|
9
9
|
| # | Step | What it does | Command |
|
|
10
10
|
|---|------|--------------|---------|
|
|
11
11
|
| 1 | **Dev install** | Install npm deps to hack on OLC itself | `npm ci && npm run build` |
|
|
12
|
-
| 2 | **Plugin activation** | Load
|
|
12
|
+
| 2 | **Plugin activation** | Load OLC as an OpenCode plugin | `npm i obsidian-lean-coder` + `opencode.json` snippet below |
|
|
13
13
|
| 3 | **Project init** | Register one app repo + vault with OLC (`initProject`, idempotent, create-only) | via the `olc-init` skill in OpenCode (the tested path) |
|
|
14
14
|
|
|
15
15
|
## 1. Dev install
|
|
@@ -26,11 +26,35 @@ npm run typecheck
|
|
|
26
26
|
|
|
27
27
|
Expected: build clean, typecheck clean. `npm test` runs the full suite (currently 140 tests). `npm pack --dry-run` shows what would ship (`dist/`, `agents/`, `skills/`, `templates/`).
|
|
28
28
|
|
|
29
|
-
>
|
|
29
|
+
> Published on npm as `obsidian-lean-coder` (MIT). Republishing needs a separate explicit approval — never publish by accident.
|
|
30
30
|
|
|
31
|
-
## 2. Plugin activation
|
|
31
|
+
## 2. Plugin activation
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
```sh
|
|
34
|
+
npm install obsidian-lean-coder
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then list it in your project's `opencode.json` (npm loaders resolve the package root `dist/index.js`, which since v0.1.1 carries the plugin default export alongside `OLC_VERSION`):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"plugins": ["obsidian-lean-coder"]
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Verify it loads (from the consuming project directory; the model call itself will fail without account funds, but plugin loading happens first):
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
OPENCODE_LOG_LEVEL=DEBUG opencode run --standalone "hi" --print-logs 2>&1 | grep -E "loading plugin.*obsidian-lean-coder|failed to load plugin"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Expected: a `loading plugin ... obsidian-lean-coder` line and **zero** `failed to load plugin` lines. (Verified 2026-10-13 via the equivalent local-file shape against the real loader; npm-registry install itself verified in OLC-071.)
|
|
52
|
+
|
|
53
|
+
> `npm install` alone shows nothing in OpenCode — that is normal. The package must be listed under `plugins`, and agents/skills never auto-appear: they are project-local files you copy yourself (next step). No restart or rebuild needed after editing `opencode.json`.
|
|
54
|
+
|
|
55
|
+
### Local dev path (this checkout, no npm)
|
|
56
|
+
|
|
57
|
+
An `index.js` under `.opencode/plugins/<name>/` auto-loads with no install step (proven in OLC-011, re-verified in OLC-071). The plugin entrypoint is `dist/plugin.js` (`src/plugin.ts` → `Plugin.define({ id: "olc" })`, one read-only `olc_status` tool, zero writes on load).
|
|
34
58
|
|
|
35
59
|
In your consuming project (replace `/home/you/olc` with your OLC checkout):
|
|
36
60
|
|
|
@@ -41,17 +65,19 @@ printf '%s\n' 'export { default } from "file://'"$PKG"'/dist/plugin.js";' > .ope
|
|
|
41
65
|
printf '%s\n' '{ "type": "module", "dependencies": { "@opencode/plugin": "2.0.27" } }' > .opencode/plugins/olc/package.json
|
|
42
66
|
```
|
|
43
67
|
|
|
44
|
-
Verify
|
|
68
|
+
Verify with the same `grep` as above, expecting `.opencode/plugins/olc/index.js` in the loading line.
|
|
69
|
+
|
|
70
|
+
Then install the agent/skill resources — recommended via the setup helper:
|
|
45
71
|
|
|
46
72
|
```sh
|
|
47
|
-
|
|
73
|
+
npx obsidian-lean-coder setup # project scope: ./.opencode
|
|
74
|
+
npx obsidian-lean-coder setup --global # global scope: ~/.config/opencode
|
|
75
|
+
npx obsidian-lean-coder setup --dry-run # preview, writes nothing
|
|
48
76
|
```
|
|
49
77
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Then place the agent/skill resources project-locally (DECISIONS.md #2 — programmatic registration was rejected for MVP):
|
|
78
|
+
Missing directories are created; existing OLC agent/skill files are overwritten with the package
|
|
79
|
+
versions (a deliberate exception to the create-only rule, scoped to these files only).
|
|
80
|
+
Manual equivalent (DECISIONS.md #2 — programmatic registration was rejected for MVP):
|
|
55
81
|
|
|
56
82
|
```sh
|
|
57
83
|
PKG=/home/you/olc # your OLC checkout
|
|
@@ -74,7 +100,7 @@ Supported versions: OpenCode 2.x with the V2 plugin API. OLC pins `@opencode/plu
|
|
|
74
100
|
|
|
75
101
|
`initProject` (`src/init/index.ts`) registers one app repo + vault. It is idempotent and **create-only**: existing files are reported `preserved`, never overwritten. Anything needing a human choice comes back as `status: "needs-decision"` — no prompting inside the module.
|
|
76
102
|
|
|
77
|
-
Run it via the `olc-init` skill inside OpenCode (recommended — the only tested path for MVP). A programmatic import is not yet wired: the package entrypoint (`dist/index.js`)
|
|
103
|
+
Run it via the `olc-init` skill inside OpenCode (recommended — the only tested path for MVP). A programmatic import is not yet wired: the package entrypoint (`dist/index.js`) exports `OLC_VERSION` plus the plugin default, and `initProject` lives in `src/init/index.ts` for internal/agent use.
|
|
78
104
|
|
|
79
105
|
What it creates (only when missing):
|
|
80
106
|
|
package/bin/olc-setup.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OLC setup helper (OLC-075).
|
|
4
|
+
*
|
|
5
|
+
* Manually run after `npm install -g obsidian-lean-coder` (or npx):
|
|
6
|
+
* olc-setup setup [--project|--global] [--dry-run]
|
|
7
|
+
*
|
|
8
|
+
* Copies the shipped agent/skill resources into OpenCode's discovery paths:
|
|
9
|
+
* project scope (default): <cwd>/.opencode/{agents,skills}
|
|
10
|
+
* global scope: ~/.config/opencode/{agents,skills}
|
|
11
|
+
* ($XDG_CONFIG_HOME/opencode when set)
|
|
12
|
+
*
|
|
13
|
+
* Behavior (locked with the user):
|
|
14
|
+
* - Missing directories are created (mkdir -p).
|
|
15
|
+
* - Existing OLC agent/skill files are OVERWRITTEN with the package
|
|
16
|
+
* versions. This is a deliberate, narrow exception to OLC's usual
|
|
17
|
+
* create-only rule — and it applies ONLY to the files this command owns
|
|
18
|
+
* (listed in OWNED_FILES below). Nothing else is touched.
|
|
19
|
+
* - `--dry-run` prints what would happen and writes nothing.
|
|
20
|
+
* - `opencode.json` is NEVER edited by this command. After it runs, it
|
|
21
|
+
* prints the manual plugin-registration snippet for README §2.
|
|
22
|
+
*
|
|
23
|
+
* Node builtins only — no runtime dependencies.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
27
|
+
import { dirname, join, resolve } from "node:path";
|
|
28
|
+
import { homedir } from "node:os";
|
|
29
|
+
import { fileURLToPath } from "node:url";
|
|
30
|
+
|
|
31
|
+
/** Files this command owns: [package-relative source, scope-relative dest]. */
|
|
32
|
+
const OWNED_FILES = [
|
|
33
|
+
["agents/olc-plan.md", ".opencode/agents/olc-plan.md"],
|
|
34
|
+
["agents/olc-build.md", ".opencode/agents/olc-build.md"],
|
|
35
|
+
["skills/olc-explore/SKILL.md", ".opencode/skills/olc-explore/SKILL.md"],
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function usage() {
|
|
39
|
+
return [
|
|
40
|
+
"Usage: olc-setup setup [--project|--global] [--dry-run]",
|
|
41
|
+
"",
|
|
42
|
+
" setup copy shipped agents/skills into OpenCode discovery paths",
|
|
43
|
+
" --project install into <cwd>/.opencode (default)",
|
|
44
|
+
" --global install into ~/.config/opencode ($XDG_CONFIG_HOME/opencode when set)",
|
|
45
|
+
" --dry-run print what would happen, write nothing",
|
|
46
|
+
"",
|
|
47
|
+
"Existing OLC agent/skill files are overwritten with the package versions;",
|
|
48
|
+
"nothing else is touched, and opencode.json is never edited (see the",
|
|
49
|
+
"manual plugin-registration snippet printed after a successful run).",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function fail(message) {
|
|
54
|
+
process.stderr.write(`olc-setup: ${message}\n${usage()}\n`);
|
|
55
|
+
process.exit(2);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseArgs(argv) {
|
|
59
|
+
if (argv[0] !== "setup") fail(`expected subcommand \"setup\", got ${JSON.stringify(argv[0] ?? "(none)")}.`);
|
|
60
|
+
let scope = "project";
|
|
61
|
+
let dryRun = false;
|
|
62
|
+
for (const arg of argv.slice(1)) {
|
|
63
|
+
if (arg === "--project") scope = "project";
|
|
64
|
+
else if (arg === "--global") scope = "global";
|
|
65
|
+
else if (arg === "--dry-run") dryRun = true;
|
|
66
|
+
else fail(`unknown argument ${JSON.stringify(arg)}.`);
|
|
67
|
+
}
|
|
68
|
+
return { scope, dryRun };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function packageRoot() {
|
|
72
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function scopeRoot(scope) {
|
|
76
|
+
if (scope === "project") return resolve(process.cwd());
|
|
77
|
+
const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
78
|
+
return resolve(base, "opencode");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function main() {
|
|
82
|
+
const { scope, dryRun } = parseArgs(process.argv.slice(2));
|
|
83
|
+
const pkg = packageRoot();
|
|
84
|
+
const root = scopeRoot(scope);
|
|
85
|
+
|
|
86
|
+
const missing = OWNED_FILES.map(([src]) => src).filter((src) => !existsSync(join(pkg, src)));
|
|
87
|
+
if (missing.length > 0) {
|
|
88
|
+
process.stderr.write(
|
|
89
|
+
`olc-setup: installed package is incomplete, missing: ${missing.join(", ")}. Reinstall obsidian-lean-coder.\n`,
|
|
90
|
+
);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const summary = [];
|
|
95
|
+
for (const [src, destRel] of OWNED_FILES) {
|
|
96
|
+
const dest = join(root, destRel);
|
|
97
|
+
const wanted = readFileSync(join(pkg, src), "utf8");
|
|
98
|
+
const prior = existsSync(dest) ? readFileSync(dest, "utf8") : null;
|
|
99
|
+
if (prior === wanted) {
|
|
100
|
+
summary.push({ file: destRel, action: "skipped" });
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!dryRun) {
|
|
104
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
105
|
+
writeFileSync(dest, wanted, "utf8");
|
|
106
|
+
}
|
|
107
|
+
summary.push({ file: destRel, action: prior === null ? "created" : "overwritten" });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const counts = { created: 0, overwritten: 0, skipped: 0 };
|
|
111
|
+
for (const entry of summary) {
|
|
112
|
+
counts[entry.action] += 1;
|
|
113
|
+
process.stdout.write(`${entry.action} ${entry.file}\n`);
|
|
114
|
+
}
|
|
115
|
+
process.stdout.write(
|
|
116
|
+
`${dryRun ? "[dry-run] " : ""}done (${scope} scope, ${root}): ` +
|
|
117
|
+
`${counts.created} created, ${counts.overwritten} overwritten, ${counts.skipped} skipped.\n`,
|
|
118
|
+
);
|
|
119
|
+
if (!dryRun) {
|
|
120
|
+
process.stdout.write(
|
|
121
|
+
"\nNext (manual): register the plugin in opencode.json so OpenCode loads it:\n" +
|
|
122
|
+
' { "plugins": ["obsidian-lean-coder"] }\n' +
|
|
123
|
+
"See README §2 for verification. opencode.json was left untouched.\n",
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OLC package entrypoint. Thin on purpose — see docs/PRD.md §8 for planned
|
|
3
3
|
* module layout (config, core, git, logging, tools, validation).
|
|
4
|
+
*
|
|
5
|
+
* The plugin default export is re-exported here (not only from
|
|
6
|
+
* `./plugin.js`) because OpenCode's npm loader resolves the package root,
|
|
7
|
+
* i.e. `dist/index.js` — without a `default` export carrying `{ id, setup }`
|
|
8
|
+
* the loader ignores the package entirely (found by OLC-071 smoke test:
|
|
9
|
+
* zero load attempts for 0.1.0). `OLC_VERSION` is only consumed inside
|
|
10
|
+
* `plugin.ts` tool `execute` (deferred to call time), so this re-export
|
|
11
|
+
* cycle is safe under ESM live bindings.
|
|
4
12
|
*/
|
|
5
|
-
export declare const OLC_VERSION = "0.
|
|
13
|
+
export declare const OLC_VERSION = "0.2.0";
|
|
14
|
+
export { default } from "./plugin.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OLC package entrypoint. Thin on purpose — see docs/PRD.md §8 for planned
|
|
3
3
|
* module layout (config, core, git, logging, tools, validation).
|
|
4
|
+
*
|
|
5
|
+
* The plugin default export is re-exported here (not only from
|
|
6
|
+
* `./plugin.js`) because OpenCode's npm loader resolves the package root,
|
|
7
|
+
* i.e. `dist/index.js` — without a `default` export carrying `{ id, setup }`
|
|
8
|
+
* the loader ignores the package entirely (found by OLC-071 smoke test:
|
|
9
|
+
* zero load attempts for 0.1.0). `OLC_VERSION` is only consumed inside
|
|
10
|
+
* `plugin.ts` tool `execute` (deferred to call time), so this re-export
|
|
11
|
+
* cycle is safe under ESM live bindings.
|
|
4
12
|
*/
|
|
5
|
-
export const OLC_VERSION = "0.
|
|
13
|
+
export const OLC_VERSION = "0.2.0";
|
|
14
|
+
export { default } from "./plugin.js";
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "obsidian-lean-coder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Obsidian Lean Coder — OpenCode extension for project-scoped planning, memory, and safe Git checkpoints.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"olc-setup": "./bin/olc-setup.js"
|
|
9
|
+
},
|
|
7
10
|
"types": "./dist/index.d.ts",
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
@@ -16,6 +19,7 @@
|
|
|
16
19
|
"agents",
|
|
17
20
|
"skills",
|
|
18
21
|
"templates",
|
|
22
|
+
"bin",
|
|
19
23
|
"README.md",
|
|
20
24
|
"CHANGELOG.md"
|
|
21
25
|
],
|