Skip to content

feat(registry): support env vars, dependencies, author, and links in skill manifest#360

Open
mahsumaktas wants to merge 2 commits intoopenclaw:mainfrom
mahsumaktas:feat/manifest-env-deps-350
Open

feat(registry): support env vars, dependencies, author, and links in skill manifest#360
mahsumaktas wants to merge 2 commits intoopenclaw:mainfrom
mahsumaktas:feat/manifest-env-deps-350

Conversation

@mahsumaktas
Copy link

@mahsumaktas mahsumaktas commented Feb 16, 2026

Summary

Closes #350

Skills that require API keys or external packages can now declare them as structured metadata in the registry manifest, replacing the current situation where these details are buried in SKILL.md prose and the security scanner flags the mismatch.

Changes

Schema (packages/schema/src/schemas.ts)

  • EnvVarDeclarationSchema: {name, required?, description?} — structured env var declarations
  • DependencyDeclarationSchema: {name, type, version?, url?, repository?} — package dependency declarations (pip/npm/brew/go/cargo/apt/other)
  • SkillLinksSchema: {homepage?, repository?, documentation?, changelog?} — project links
  • All three added as optional fields on ClawdisSkillMetadataSchema (+ author: string?)

Parser (convex/lib/skills.ts)

  • Parse envVars, dependencies, author, links from the clawdis metadata block
  • Fallback: when no clawdis block exists, parse these from top-level frontmatter keys (env:, dependencies:, author:, links:) — exactly the format proposed in Support declaring required env vars and dependencies in registry manifest #350
  • envVars accepts both structured objects and simple string arrays (strings → {name, required: true})
  • Unknown dependency types normalize to "other"

UI (src/components/SkillInstallCard.tsx)

  • Environment variables panel: shows each env var with required/optional badge and description
  • Dependencies panel: name, type, version, links to PyPI/npm/source
  • Links panel: homepage, repository, documentation

Security (convex/lib/securityPrompt.ts)

  • Updated evaluator prompt to recognize envVars alongside requires.env and primaryEnv, reducing false positives from the mismatch the issue describes

Tests (convex/lib/skills.test.ts)

7 new test cases:

  1. Parse envVars from clawdis block (with descriptions)
  2. Parse dependencies from clawdis block
  3. Parse author and links from clawdis block
  4. Parse env/deps/author/links from top-level frontmatter (no clawdis block)
  5. Handle string-only env arrays
  6. Normalize unknown dependency types to "other"
  7. Return undefined when no declarations present

All 27 tests pass ✅ (20 existing + 7 new)

Frontmatter Examples

In clawdis block (recommended)

---
metadata:
  clawdis:
    envVars:
      - name: ANTHROPIC_API_KEY
        required: true
        description: API key for Claude
      - name: MAX_TURNS
        required: false
        description: Max turns per phase (default 50)
    dependencies:
      - name: securevibes
        type: pip
        version: ">=0.3.0"
        url: https://pypi.org/project/securevibes/
    author: anshumanbh
    links:
      homepage: https://securevibes.ai
      repository: https://github.com/anshumanbh/securevibes
---

Top-level frontmatter (fallback)

---
name: my-skill
env:
  - name: MY_API_KEY
    required: true
    description: Main API key
dependencies:
  - name: requests
    type: pip
author: someuser
links:
  homepage: https://example.com
---

Backward Compatibility

  • All new fields are optional — existing skills are unaffected
  • The existing requires.env (string array) and primaryEnv continue to work as before
  • envVars provides richer metadata (descriptions, required flag) alongside the existing system
  • No database migration needed — clawdis is stored as v.optional(v.any())

Greptile Summary

This PR adds structured metadata support for environment variables, dependencies, author info, and project links in skill manifests. It extends the schema with three new declarations (EnvVarDeclarationSchema, DependencyDeclarationSchema, SkillLinksSchema), adds parsing in the backend with a fallback path for top-level frontmatter keys (when no clawdis block exists), renders the new metadata in the SkillInstallCard UI, and updates the security evaluator prompt to recognize envVars.

  • All new fields are optional and backward-compatible — existing skills are unaffected
  • 7 new tests cover clawdis block parsing, top-level frontmatter fallback, string shorthand, type normalization, and the empty case
  • The fallback path (parseFrontmatterLevelDeclarations) means skills with top-level author, env, dependencies, or links keys will now produce a non-undefined clawdis result where they previously returned undefined — downstream code uses optional chaining so this should be safe
  • Minor UI concern: env vars without an explicit required field display as "required" by default, which may not match the author's intent

Confidence Score: 4/5

  • This PR is safe to merge — all changes are additive and backward-compatible with good test coverage.
  • The implementation is clean and well-tested with 7 new test cases. All new schema fields are optional, so no breaking changes. The two issues found are style-level (UI display default for undefined required flag, and potential duplicate React keys), not correctness bugs. The fallback parsing path is a minor behavioral change but is handled safely by existing optional chaining patterns.
  • src/components/SkillInstallCard.tsx has two minor UI concerns worth addressing.

Last reviewed commit: 7588e3e

(5/5) You can turn off certain types of comments like style here!

Context used:

  • Context from dashboard - AGENTS.md (source)

…skill manifest

Closes openclaw#350

Add structured declarations for environment variables, package
dependencies, author identity, and project links to the skill
registry manifest. These fields can be declared in the clawdis
metadata block or as top-level frontmatter keys.

Changes:
- schema: add EnvVarDeclaration, DependencyDeclaration, SkillLinks
  types to ClawdisSkillMetadata
- parser: extract envVars, dependencies, author, links from both
  clawdis block and top-level frontmatter (fallback for skills
  without a clawdis block)
- UI: render env vars with required/optional badges and descriptions,
  dependencies with type/version/links, and project links in the
  skill detail page install card
- security: update evaluator prompt to recognize envVars alongside
  requires.env and primaryEnv
- tests: 7 new test cases covering all declaration formats
@vercel
Copy link
Contributor

vercel bot commented Feb 16, 2026

@mahsumaktas is attempting to deploy a commit to the Amantus Machina Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 84 to 88
{env.required === false ? (
<span style={{ color: 'var(--ink-soft)', fontSize: '0.75rem' }}>optional</span>
) : (
<span style={{ color: 'var(--ink-accent)', fontSize: '0.75rem' }}>required</span>
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undefined required displays as "required"

When a skill author declares an env var as { name: "FOO" } without specifying required, the field is undefined (per the schema's boolean?). The condition env.required === false only catches explicit false, so undefined falls through to the else branch and shows "required". This could misrepresent env vars where the author intentionally omitted the flag (meaning "unspecified"), showing them as mandatory.

Consider treating undefined differently, e.g. showing no badge or a distinct label:

Suggested change
{env.required === false ? (
<span style={{ color: 'var(--ink-soft)', fontSize: '0.75rem' }}>optional</span>
) : (
<span style={{ color: 'var(--ink-accent)', fontSize: '0.75rem' }}>required</span>
)}
{env.required === false ? (
<span style={{ color: 'var(--ink-soft)', fontSize: '0.75rem' }}>optional</span>
) : env.required === true ? (
<span style={{ color: 'var(--ink-accent)', fontSize: '0.75rem' }}>required</span>
) : null}
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/components/SkillInstallCard.tsx
Line: 84:88

Comment:
**Undefined `required` displays as "required"**

When a skill author declares an env var as `{ name: "FOO" }` without specifying `required`, the field is `undefined` (per the schema's `boolean?`). The condition `env.required === false` only catches explicit `false`, so `undefined` falls through to the else branch and shows "required". This could misrepresent env vars where the author intentionally omitted the flag (meaning "unspecified"), showing them as mandatory.

Consider treating `undefined` differently, e.g. showing no badge or a distinct label:

```suggestion
                        {env.required === false ? (
                          <span style={{ color: 'var(--ink-soft)', fontSize: '0.75rem' }}>optional</span>
                        ) : env.required === true ? (
                          <span style={{ color: 'var(--ink-accent)', fontSize: '0.75rem' }}>required</span>
                        ) : null}
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 81 to 82
{envVars.map((env) => (
<div key={env.name} style={{ display: 'flex', alignItems: 'baseline', gap: '0.5rem' }}>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible duplicate React keys in environment variable list

The key prop uses only the variable's identifier, which assumes uniqueness. If a manifest accidentally declares the same identifier twice, React will warn about duplicate keys. The dependencies list at line 107 handles this more robustly by appending the array index to the key. Consider applying the same pattern here for consistency.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/components/SkillInstallCard.tsx
Line: 81:82

Comment:
**Possible duplicate React keys in environment variable list**

The `key` prop uses only the variable's identifier, which assumes uniqueness. If a manifest accidentally declares the same identifier twice, React will warn about duplicate keys. The dependencies list at line 107 handles this more robustly by appending the array index to the key. Consider applying the same pattern here for consistency.

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

The packages/schema/dist/ directory was out of sync with the source files, missing new TypeScript types that consumers depend on.

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support declaring required env vars and dependencies in registry manifest

1 participant