Skip to content

feat(skills): add skill upload/download with zip and folder support#68

Merged
furtherref merged 1 commit into
mainfrom
feat/skill-upload-download
May 24, 2026
Merged

feat(skills): add skill upload/download with zip and folder support#68
furtherref merged 1 commit into
mainfrom
feat/skill-upload-download

Conversation

@furtherref
Copy link
Copy Markdown
Owner

@furtherref furtherref commented May 23, 2026

Summary

  • Add a new Upload file method to the skill creation dialog, supporting local .zip archives and folder uploads containing SKILL.md
  • Multi-skill zip archives trigger a bulk import flow with checkboxes, progress bar, cancel support, and result summary
  • Add a download button on the skill detail page that exports the skill (SKILL.md + supporting files) as a .zip file
  • Full i18n support (en + zh-Hans) for all new UI strings and error messages

Details

Upload (create-skill-dialog)

  • Browser-side zip parsing via fflate (new catalog dependency)
  • Client-side SKILL.md frontmatter extraction for name/description pre-fill
  • Drag-and-drop for .zip files + folder picker via webkitdirectory
  • Single-skill mode: editable name/description fields before submit
  • Bulk mode (2+ skills in zip): select-all toggle, per-skill checkbox list, sequential import with progress and summary
  • Submits via existing POST /api/skills endpoint — no backend changes needed

Download (skill-detail-page)

  • Download button visible to all viewers (not gated by edit permission)
  • Generates zip in-browser with skill name as root folder, containing SKILL.md + supporting files
  • Zip format matches upload format for round-trip compatibility

Security hardening (from code review)

  • Reject dotfiles at any path level (.env, .config, etc.)
  • Sanitize skill names in zip entries to prevent path traversal (/, ..)
  • Cancel in-flight bulk imports on component unmount
  • Show truncation warning when supporting files exceed size/count limits

Test plan

  • Upload a single-skill .zip → verify name/description pre-filled from frontmatter, skill created
  • Upload a multi-skill .zip (e.g. 归档2.zip with 2 folders) → verify bulk list, select/deselect, import progress and summary
  • Upload a folder via folder picker → verify SKILL.md found and skill created
  • Drop a non-zip file → verify localized error message
  • Upload a zip without SKILL.md → verify localized error message
  • Upload a skill with a name that already exists → verify localized conflict error (no mixed-language text)
  • Switch language to Chinese → verify all error messages display in Chinese
  • Download a skill from detail page → verify zip contains correct folder structure
  • Re-upload a downloaded zip → verify round-trip works
  • Locale parity test passes (pnpm --filter @multica/views exec vitest run locales/parity.test.ts)
  • Full typecheck passes (pnpm typecheck)

🤖 Generated with Claude Code

@vercel
Copy link
Copy Markdown

vercel Bot commented May 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
multica-web Ready Ready Preview, Comment May 24, 2026 1:41pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
multica-docs Ignored Ignored Preview May 24, 2026 1:41pm

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b8358a3f0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/views/skills/lib/parse-skill-bundle.ts
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/components/skill-detail-page.tsx Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42e6139252

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/components/skill-detail-page.tsx Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2f532b50a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/views/skills/components/skill-detail-page.tsx Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/components/create-skill-dialog.tsx
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7cd50c7247

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/views/skills/lib/parse-skill-bundle.ts
Comment thread packages/views/skills/lib/parse-skill-bundle.ts
Comment thread packages/views/skills/components/create-skill-dialog.tsx Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts Outdated
Comment thread packages/views/skills/lib/parse-skill-bundle.ts
Add "Upload file" method to skill creation dialog for importing from
.zip archives or folders. Multi-skill zips trigger bulk import.
Download button on skill detail page exports as .zip.

- fflate zip parsing; SKILL.md frontmatter extraction
- Drag-and-drop .zip, folder picker, bulk import with progress
- Upload and download use updateFrontmatter with YAML-safe escaping
  to sync edited name/description into SKILL.md content
- File.size check before arrayBuffer() for zip size guard
- Full i18n (en + zh-Hans)
- Path policy: rejects traversal/control chars/drive letters/SKILL.md
  variants/dot-prefixed directories/sensitive dotfiles (.env, .npmrc,
  .netrc); allows safe dot-prefixed leaf files (.gitignore etc.);
  case-insensitive collision detection; hidden SKILL.md root
  rejection with subtree suppression; zip inflation filter;
  50 MiB cap; binary blocklist
- 62 unit tests

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@furtherref furtherref force-pushed the feat/skill-upload-download branch from 7cd50c7 to b8fd732 Compare May 24, 2026 13:39
@furtherref furtherref merged commit db8d0a7 into main May 24, 2026
7 checks passed
@furtherref furtherref deleted the feat/skill-upload-download branch May 24, 2026 13:45
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.

1 participant