@hasna/skills 0.1.42 → 0.1.44

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,14 @@
1
+ export type SkillsCliMcpParityDomain = "discovery" | "portable-skills" | "runtime" | "validation";
2
+ export interface SkillsCliMcpParityEntry {
3
+ domain: SkillsCliMcpParityDomain;
4
+ operation: string;
5
+ cliCommands: string[];
6
+ mcpTools: string[];
7
+ jsonContracts: string[];
8
+ status: "matched" | "intentional-gap";
9
+ notes?: string;
10
+ }
11
+ export declare const SKILLS_CLI_MCP_PARITY: SkillsCliMcpParityEntry[];
12
+ export declare function validateSkillsCliMcpParity(): string[];
13
+ export declare function findSkillsParityForCliCommand(command: string): SkillsCliMcpParityEntry | undefined;
14
+ export declare function findSkillsParityForMcpTool(tool: string): SkillsCliMcpParityEntry | undefined;
@@ -15,7 +15,7 @@ export interface JsonSchemaObject {
15
15
  additionalProperties?: boolean | JsonSchemaObject;
16
16
  oneOf?: JsonSchemaObject[];
17
17
  }
18
- export type McpToolCategory = "agent-session" | "discovery" | "execution" | "feedback" | "metadata" | "pinning" | "scheduling" | "validation";
18
+ export type McpToolCategory = "agent-session" | "discovery" | "execution" | "feedback" | "metadata" | "pinning" | "scaffolding" | "scheduling" | "validation";
19
19
  export type McpToolSideEffect = "filesystem" | "local-process-or-remote-run" | "none" | "schedule-state";
20
20
  export interface McpToolContract {
21
21
  name: string;
@@ -0,0 +1,79 @@
1
+ import type { SkillMeta } from "./registry-types.js";
2
+ import { type SkillValidationResult } from "./skill-validation.js";
3
+ export declare const PORTABLE_SKILL_STANDARD = "hasna.skill.v1";
4
+ export declare const PORTABLE_SKILL_SCHEMA = "https://hasna.dev/schemas/skill.v1.json";
5
+ export declare const PORTABLE_SKILL_DEFAULT_VERSION = "0.1.0";
6
+ export interface PortableSkillInput {
7
+ name: string;
8
+ type: string;
9
+ required?: boolean;
10
+ description?: string;
11
+ }
12
+ export interface PortableSkillCommand {
13
+ name: string;
14
+ description?: string;
15
+ entry?: string;
16
+ command?: string;
17
+ args?: string[];
18
+ }
19
+ export interface PortableSkillManifest {
20
+ $schema?: string;
21
+ standard: typeof PORTABLE_SKILL_STANDARD | string;
22
+ name: string;
23
+ description: string;
24
+ version: string;
25
+ displayName?: string;
26
+ category?: string;
27
+ tags?: string[];
28
+ inputs: PortableSkillInput[];
29
+ commands: PortableSkillCommand[];
30
+ }
31
+ export interface PortableSkillSummary {
32
+ name: string;
33
+ displayName: string;
34
+ description: string;
35
+ version: string;
36
+ path: string;
37
+ commands: PortableSkillCommand[];
38
+ source: "custom";
39
+ standard: string;
40
+ }
41
+ export interface PortableSkillOptions {
42
+ rootDir?: string;
43
+ homeDir?: string;
44
+ }
45
+ export interface ScaffoldPortableSkillOptions extends PortableSkillOptions {
46
+ description?: string;
47
+ overwrite?: boolean;
48
+ }
49
+ export interface PortPortableSkillOptions extends PortableSkillOptions {
50
+ name?: string;
51
+ overwrite?: boolean;
52
+ }
53
+ export interface PortableSkillWriteResult {
54
+ name: string;
55
+ path: string;
56
+ manifest: PortableSkillManifest;
57
+ created: boolean;
58
+ }
59
+ export interface PortableSkillRunOptions extends PortableSkillOptions {
60
+ stdio?: "inherit" | "pipe";
61
+ env?: Record<string, string>;
62
+ }
63
+ export interface PortableSkillRunResult {
64
+ exitCode: number;
65
+ stdout?: string;
66
+ stderr?: string;
67
+ error?: string;
68
+ }
69
+ export declare function normalizePortableSkillName(name: string): string;
70
+ export declare function getPortableSkillsRoot(options?: PortableSkillOptions): string;
71
+ export declare function getPortableSkillPath(name: string, options?: PortableSkillOptions): string;
72
+ export declare function findPortableSkill(name: string, options?: PortableSkillOptions): PortableSkillSummary | null;
73
+ export declare function listPortableSkills(options?: PortableSkillOptions): PortableSkillSummary[];
74
+ export declare function listPortableSkillMetas(options?: PortableSkillOptions): SkillMeta[];
75
+ export declare function readPortableSkillManifest(skillPath: string, fallbackName?: string): PortableSkillManifest;
76
+ export declare function scaffoldPortableSkill(name: string, options?: ScaffoldPortableSkillOptions): PortableSkillWriteResult;
77
+ export declare function portPortableSkill(sourcePath: string, options?: PortPortableSkillOptions): PortableSkillWriteResult;
78
+ export declare function validatePortableSkillDirectory(name: string, skillPath: string): SkillValidationResult;
79
+ export declare function runPortableSkill(name: string, args: string[], options?: PortableSkillRunOptions): Promise<PortableSkillRunResult>;
@@ -8,7 +8,7 @@ export type { Category, SkillMeta, SkillRegistryProfile };
8
8
  export declare function isBasicSkillName(name: string): boolean;
9
9
  /**
10
10
  * Load the full registry: official skills merged with global custom skills
11
- * from ~/.hasna/skills/custom/.
11
+ * from ~/.hasna/skills/<name>/ and the legacy ~/.hasna/skills/custom/<name>/ path.
12
12
  *
13
13
  * Custom skills with the same name as official skills take precedence.
14
14
  * Results are cached for 5 seconds.
@@ -1,4 +1,5 @@
1
1
  import type { SkillMeta } from "./registry.js";
2
+ import type { PortableSkillManifest } from "./portable-skills.js";
2
3
  export interface SkillValidationMessage {
3
4
  code: string;
4
5
  message: string;
@@ -15,6 +16,7 @@ export interface SkillValidationResult {
15
16
  binCommands: string[];
16
17
  docFiles: string[];
17
18
  skillMdFrontmatter?: SkillFrontmatter;
19
+ portableManifest?: PortableSkillManifest;
18
20
  provenance?: SkillValidationProvenance;
19
21
  runtime?: "local" | "hosted";
20
22
  };
@@ -0,0 +1,126 @@
1
+ # Portable Skill Standard
2
+
3
+ Portable skills live in one folder each:
4
+
5
+ ```text
6
+ ~/.hasna/skills/<skill-name>/
7
+ ├── SKILL.md
8
+ ├── skill.json
9
+ ├── AGENTS.md
10
+ ├── package.json
11
+ ├── tsconfig.json
12
+ └── src/
13
+ └── index.ts
14
+ ```
15
+
16
+ `skills new <name>` creates this layout. `skills scaffold <name>` is an alias.
17
+ `skills port <path>` and `skills add <path>` copy an existing skill folder into
18
+ this layout and add missing standard files.
19
+
20
+ ## Naming
21
+
22
+ Skill names are lowercase slugs: letters, numbers, dots, underscores, and
23
+ hyphens. The folder name, `SKILL.md` frontmatter `name`, `skill.json` `name`,
24
+ and `package.json` `name` should match.
25
+
26
+ ## Manifest
27
+
28
+ Every portable skill needs a manifest. `skill.json` is the machine-readable
29
+ manifest. `SKILL.md` frontmatter stays compatible with existing Codewith
30
+ `SKILL.md` conventions and can be used by agents for skill discovery.
31
+
32
+ Minimum `SKILL.md` frontmatter:
33
+
34
+ ```yaml
35
+ ---
36
+ name: my-skill
37
+ description: What this skill does and when to use it.
38
+ version: 0.1.0
39
+ source: custom
40
+ category: Development Tools
41
+ tags:
42
+ - custom
43
+ ---
44
+ ```
45
+
46
+ Minimum `skill.json`:
47
+
48
+ ```json
49
+ {
50
+ "$schema": "https://hasna.dev/schemas/skill.v1.json",
51
+ "standard": "hasna.skill.v1",
52
+ "name": "my-skill",
53
+ "description": "What this skill does and when to use it.",
54
+ "version": "0.1.0",
55
+ "inputs": [
56
+ {
57
+ "name": "args",
58
+ "type": "string[]",
59
+ "required": false,
60
+ "description": "Arguments passed after `skills run my-skill`."
61
+ }
62
+ ],
63
+ "commands": [
64
+ {
65
+ "name": "my-skill",
66
+ "entry": "src/index.ts",
67
+ "description": "Run my-skill.",
68
+ "args": ["...args"]
69
+ }
70
+ ]
71
+ }
72
+ ```
73
+
74
+ If `skill.json` is absent, the CLI can infer a portable manifest from
75
+ `SKILL.md` frontmatter plus `package.json` `bin`, but scaffolded and ported
76
+ skills should keep `skill.json` checked in.
77
+
78
+ ## Agent Handoff
79
+
80
+ `AGENTS.md` is required for portable skills created or ported by the CLI. It
81
+ tells a coding agent where to put logic, how to update the manifest, how to test
82
+ the skill, and how to verify it with:
83
+
84
+ ```bash
85
+ skills validate my-skill
86
+ skills run my-skill --help
87
+ ```
88
+
89
+ ## Runtime
90
+
91
+ The first command in `skill.json.commands` is the default for:
92
+
93
+ ```bash
94
+ skills run my-skill [args...]
95
+ ```
96
+
97
+ For Bun/TypeScript skills, point `entry` at `src/index.ts`. The CLI runs the
98
+ entry from the skill folder, passes through arguments, and records run metadata
99
+ under the caller project’s `.skills/runs` and `.skills/exports` directories.
100
+
101
+ ## Validation
102
+
103
+ ```bash
104
+ skills validate my-skill --json
105
+ ```
106
+
107
+ Validation checks:
108
+
109
+ - folder and name safety;
110
+ - `SKILL.md` frontmatter compatibility;
111
+ - `skill.json` standard, version, inputs, and commands;
112
+ - `AGENTS.md` presence;
113
+ - `package.json` and command entrypoint safety;
114
+ - no reserved files such as `.env` or symlinks.
115
+
116
+ ## Porting Existing Skills
117
+
118
+ ```bash
119
+ skills port ./old-skill
120
+ skills add ./old-skill --name new-name
121
+ ```
122
+
123
+ Porting copies the folder into `~/.hasna/skills/<name>/`, skips generated and
124
+ dependency directories such as `node_modules`, `dist`, and `.git`, then adds or
125
+ normalizes `skill.json`, `AGENTS.md`, `package.json`, `tsconfig.json`, and an
126
+ entrypoint when they are missing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,6 +19,7 @@
19
19
  "!dist/platform",
20
20
  "!dist/server",
21
21
  "bin/",
22
+ "docs/skill-standard.md",
22
23
  "skills/",
23
24
  "!skills/**/node_modules",
24
25
  "!skills/scaffold-project/my-app",
@@ -63,7 +64,6 @@
63
64
  "typescript": "^5"
64
65
  },
65
66
  "dependencies": {
66
- "@hasna/events": "^0.1.3",
67
67
  "@modelcontextprotocol/sdk": "^1.26.0",
68
68
  "chalk": "^5.3.0",
69
69
  "commander": "^12.1.0",
@@ -0,0 +1,5 @@
1
+ {
2
+ "env": {
3
+ "CLAUDE_CODE_TASK_LIST_ID": "service-apidocs-dev"
4
+ }
5
+ }