Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "wisdom-lens",
"version": "1.2.1",
"description": "Decision frameworks, AI failure diagnostics, and operating principles for consequential work.",
"skills": "./skills/"
}
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ Distilled into actionable frameworks for modern professionals:
- **The Wisdom Playbook** — 20 chapters covering mind, work, people, and the core self
- **The New Lens** — 16 chapters mapping AI-age failure modes and the builder's protocol

## Install and load

The same `skills/` directory is packaged without duplicated skill content:

- **Claude Code:** install this repository as a plugin using `.claude-plugin/plugin.json` (existing support is unchanged).
- **Codex:** install the repository as a plugin; `.codex-plugin/plugin.json` points Codex at `skills/`.
- **Kimi Code CLI:** run `/plugins install https://github.com/CodeWithJuber/wisdomlens`, then `/reload`. Kimi reads `kimi.plugin.json`.
- **OpenClaw:** review the bundle, then run `openclaw plugins install https://github.com/CodeWithJuber/wisdomlens --accept-capabilities`. OpenClaw maps the Codex bundle's skill root; the existing Claude prompt hooks are detected but not executed by OpenClaw.

Start a new session after installation. These are instruction-only skills: they add no executable tools, credentials, or network access. Host permissions and approval policies still apply.

## Provenance and safety

Wisdom Lens is an author-created operational synthesis presented through two named frameworks, **The Wisdom Playbook** and **The New Lens**. Earlier public repository metadata described the work as distilled from ancient wisdom texts, but this package does not include source passages or citation mappings sufficient to verify each principle against an original source.

Treat the skills as authorial interpretation and practical guidance—not original source text, a canonical translation, a religious ruling, or professional legal, medical, financial, or safety advice. For consequential decisions, verify claims against primary sources and consult a qualified human where appropriate. The package contains repository-authored skill material only; it does not bundle user profiles, session logs, or private agent memory.

## Skills

| Skill | Triggers |
Expand Down Expand Up @@ -40,3 +57,7 @@ Each skill includes detailed reference files:
## Philosophy

All terminology is universal and generic. The principles are framework-agnostic and apply to any professional context — leadership, product development, team management, personal growth, or building with AI tools.

## Validation

Run `node scripts/validate.mjs` to check every `SKILL.md` name, description, directory match, relative reference, package manifest, and the private-memory exclusion.
10 changes: 10 additions & 0 deletions kimi.plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "wisdom-lens",
"version": "1.2.1",
"description": "Decision frameworks, AI failure diagnostics, and operating principles for consequential work.",
"skills": "./skills/",
"interface": {
"displayName": "Wisdom Lens",
"shortDescription": "Structured judgment and AI-workflow guidance"
}
}
122 changes: 122 additions & 0 deletions scripts/validate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env node

import { existsSync, readFileSync, readdirSync } from "node:fs";
import { dirname, join, relative, resolve, sep } from "node:path";
import { fileURLToPath } from "node:url";

const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const errors = [];

function fail(message) {
errors.push(message);
}

function readJson(path) {
try {
return JSON.parse(readFileSync(path, "utf8"));
} catch (error) {
fail(`${relative(root, path)}: invalid JSON (${error.message})`);
return {};
}
}

function filesUnder(path) {
return readdirSync(path, { withFileTypes: true }).flatMap((entry) => {
const child = join(path, entry.name);
return entry.isDirectory() ? filesUnder(child) : [child];
});
}

function scalar(frontmatter, key) {
const match = frontmatter.match(new RegExp(`^${key}:\\s*(.*)$`, "m"));
if (!match) return "";
const value = match[1].trim();
if (value === ">" || value === "|") {
const after = frontmatter.slice(match.index + match[0].length);
const lines = after.match(/^(?:\r?\n[ \t]+[^\r\n]*)+/)?.[0] ?? "";
return lines.replace(/\r?\n[ \t]+/g, " ").trim();
}
return value.replace(/^(["'])(.*)\1$/, "$2");
}

const skillFiles = filesUnder(join(root, "skills")).filter(
(path) => path.endsWith(`${sep}SKILL.md`),
);

if (skillFiles.length === 0) fail("skills/: no SKILL.md files found");

for (const path of skillFiles) {
const label = relative(root, path);
const text = readFileSync(path, "utf8");
const frontmatter = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
if (!frontmatter) {
fail(`${label}: missing closed YAML frontmatter`);
continue;
}

const name = scalar(frontmatter, "name");
const description = scalar(frontmatter, "description");
const directory = dirname(path).split(sep).at(-1);

if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name) || name.length > 64) {
fail(`${label}: name must be a 1-64 character lowercase kebab-case slug`);
}
if (name !== directory) fail(`${label}: name must match parent directory '${directory}'`);
if (!description || description.length > 1024) {
fail(`${label}: description must contain 1-1024 characters`);
}

const references = [
...text.matchAll(/\[[^\]]*\]\((?!https?:|#|mailto:)([^)]+)\)/g),
...text.matchAll(/`((?:references|scripts|assets)\/[^`]+)`/g),
].map((match) => match[1].split("#", 1)[0]);

for (const reference of references) {
const target = resolve(dirname(path), reference);
if (!target.startsWith(`${dirname(path)}${sep}`) || !existsSync(target)) {
fail(`${label}: missing or unsafe relative reference '${reference}'`);
}
}
}

const manifests = [
[".claude-plugin/plugin.json", "skills"],
[".codex-plugin/plugin.json", "skills"],
["kimi.plugin.json", "skills"],
];

for (const jsonPath of [".claude-plugin/marketplace.json", "hooks/hooks.json"]) {
readJson(join(root, jsonPath));
}

for (const [manifestPath, skillsKey] of manifests) {
const path = join(root, manifestPath);
if (!existsSync(path)) {
fail(`${manifestPath}: missing manifest`);
continue;
}
const manifest = readJson(path);
if (manifest.name !== "wisdom-lens") fail(`${manifestPath}: unexpected plugin name`);
if (manifest.version !== "1.2.1") fail(`${manifestPath}: version must match 1.2.1`);
const skillsPath = resolve(root, manifest[skillsKey] ?? "");
if (skillsPath !== join(root, "skills") || !existsSync(skillsPath)) {
fail(`${manifestPath}: skills must resolve to ./skills/`);
}
}

for (const path of filesUnder(root)) {
const repoPath = relative(root, path).replaceAll("\\", "/");
if (repoPath.startsWith(".git/")) continue;
if (/(^|\/)(MEMORY\.md|USER\.md)$/i.test(repoPath) || /(^|\/)memory\//i.test(repoPath)) {
fail(`${repoPath}: private agent-memory files must not be packaged`);
}
}

if (errors.length) {
console.error(errors.map((error) => `- ${error}`).join("\n"));
process.exit(1);
}

console.log(
`Validated ${skillFiles.length} skills, ${manifests.length} package manifests, 2 supporting JSON files, and relative references.`,
);