用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill entity-schema-manager命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
基于 SOC 职业分类
正在显示 SKILL.md
| name | entity-schema-manager |
| description | > Use when this capability is needed. |
Interact with the Entity Schema Manager plugin to query, create, and manage structured entities in an Obsidian vault.
// Direct API access - primary method
const api = window['entity-schema-manager.api.v1'];
// Alternative: plugin registry access
const plugin = app.plugins.plugins['entity-schema-manager'];
const api = plugin?.api;
// Check availability
if (!api) {
// Fall back to reading entity-schemas.json from vault root
const schemas = JSON.parse(await app.vault.adapter.read('entity-schemas.json'));
}
// Read schema definitions directly
const schemasPath = `${vaultPath}/entity-schemas.json`;
const schemas = JSON.parse(fs.readFileSync(schemasPath, 'utf-8'));
// Read entities by scanning markdown files
// Use frontmatter parsing + schema matching logic
// See references/agent-patterns.md for complete external agent patterns
Quick reference for mapping user questions to API calls:
| User Asks | API Pattern | Example Response |
|---|---|---|
| "What kinds of entities do I have?" | api.getEntityTypeNames() | "You have: Person, Team, Project" |
| "How many people are there?" | api.getEntitySummary()['Person'] | "5 Person entities" |
| "Show me all teams" | api.getEntitiesByType('Team') | Table of team names and files |
| "What's missing from my entities?" | api.getEntityValidation('Person') | List of entities with missing props |
| "Who's on Team X?" | Filter entities by property | List of people with team=X |
| "What references this person?" | Traverse entity links | List of entities linking to target |
// Get all entity type names
const types = api.getEntityTypeNames(); // ['Person', 'Team', ...]
// Check if type exists
const exists = api.hasEntityType('Person'); // true/false
// Get full schema definitions
const schemas = api.getEntitySchemas();
// Get all entities of a type
const people = api.getEntitiesByType('Person');
// Returns: [{ file, entityType, properties, missingProperties }]
// Get entity counts
const summary = api.getEntitySummary(); // { Person: 5, Team: 2 }
// Validate entities
const validation = api.getEntityValidation('Person');
// Returns: { total, valid, withIssues, issues: ['file.md: missing email'] }
// 1. Get template with default values
const template = api.getEntityTemplate('Person');
// Returns: { name: '', role: '', team: '', is: 'atlas/entities/person' }
// 2. Get schema for folder path
const schema = api.getEntitySchemas().find(s => s.name === 'Person');
const folder = schema.matchCriteria.folderPath; // 'atlas/notes'
// 3. Generate frontmatter YAML
const yaml = Object.entries(template)
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
.join('\n');
// 4. Create file at correct location
const content = `---\n${yaml}\n---\n\n# ${entityName}`;
await app.vault.create(`${folder}/${filename}.md`, content);
// Read file, parse frontmatter, add property, write back
async function addProperty(file, propName, value) {
const content = await app.vault.read(file);
const newContent = addPropertyToFrontmatter(content, propName, value);
await app.vault.modify(file, newContent);
}
function addPropertyToFrontmatter(content, propName, value) {
const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
const match = content.match(frontmatterRegex);
if (match) {
const frontmatter = match[1];
const newFrontmatter = `${frontmatter}\n${propName}: ${JSON.stringify(value)}`;
return content.replace(frontmatterRegex, `---\n${newFrontmatter}\n---`);
} else {
// No existing frontmatter
return `---\n${propName}: ${JSON.stringify(value)}\n---\n\n${content}`;
}
}
// Update property across all entities of a type
const entities = api.getEntitiesByType('Person');
for (const entity of entities) {
await addProperty(entity.file, 'department', 'Engineering');
}
Given a file and its frontmatter, determine its entity type with complete edge case handling:
function identifyEntityType(file, frontmatter) {
const schemas = api.getEntitySchemas();
for (const schema of schemas) {
if (matchesSchema(file, frontmatter, schema)) {
return {
type: schema.name,
schema: schema,
missingRequired: findMissingRequired(frontmatter, schema)
};
}
}
return { type: null, schema: null, missingRequired: [] };
}
function matchesSchema(file, frontmatter, schema) {
const c = schema.matchCriteria;
// Check folder path
if (c.folderPath && !file.path.startsWith(c.folderPath)) return false;
// Check required properties exist
if (c.requiredProperties) {
for (const prop of c.requiredProperties) {
if (!(prop in frontmatter)) return false;
}
}
// Check property values (with Obsidian link normalization)
if (c.) {
( [key, expected] .(c.)) {
(!(frontmatter[key], expected)) ;
}
}
;
}
() {
= v => (v || )
.(, )
.()[]
.(, )
.();
(actual) === (expected);
}
() {
missing = [];
( [propName, propDef] .(schema.)) {
(propDef. && !(propName frontmatter)) {
missing.(propName);
}
}
missing;
}
For Templater plugin users:
// Get data for tp.system.suggester (entity type picker)
const { names, values } = TemplaterHelpers.getEntityTypeSuggesterData();
const selected = await tp.system.suggester(names, values);
// Get entities for linking
const { names, values } = TemplaterHelpers.getEntitySuggesterData('Person');
const person = await tp.system.suggester(names, values);
// Generate ready-to-use YAML frontmatter
const yaml = TemplaterHelpers.generateFrontmatterYAML('Person');
When API unavailable, read entity-schemas.json from vault root:
const content = await app.vault.adapter.read('entity-schemas.json');
const schemas = JSON.parse(content);
// schemas is array of EntitySchema objects with same structure as API
// Use matching logic above to identify entity types
| Field | Type | Description |
|---|---|---|
name | string | Entity type name (e.g., "Person") |
properties | object | Property definitions with type/required |
matchCriteria.folderPath | string | Required folder prefix |
matchCriteria.requiredProperties | string[] | Properties that must exist |
matchCriteria.propertyValues | object | Property values to match |
description | string | Human-readable description |
Default organization uses "atlas" folders:
atlas/entities/ - Entity type definitions (person.md, team.md)atlas/notes/ - Entity instancesis: [[atlas/entities/person]] propertyConverted and distributed by TomeVault — claim your Tome and manage your conversions.