Skip to content

feat(connections): import device skills into the agent#3869

Merged
louis030195 merged 1 commit into
mainfrom
claude/festive-khorana-eaec85
Jun 5, 2026
Merged

feat(connections): import device skills into the agent#3869
louis030195 merged 1 commit into
mainfrom
claude/festive-khorana-eaec85

Conversation

@louis030195

@louis030195 louis030195 commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a Skills card to Settings › Connections (right next to MCP servers). Connect skills opens a modal that finds the SKILL.md skills already on your device and imports the ones you pick, so screenpipe's agent can use them, in chat and in every pipe.

A "skill" is just a folder with a SKILL.md (YAML frontmatter plus markdown instructions), the same format Claude Code uses.


UI and user flow

1. A new "Skills" card in Connections

Sits beside "MCP servers". When nothing is imported yet the button reads Connect skills; once you have skills it becomes Manage with a count.

Skills card in connections

2. Clicking it opens the importer, which scans your device

  • Scans ~/.claude/skills for SKILL.md folders.
  • Each card shows the skill's name and description (parsed from frontmatter) plus where it was found.
  • The dashed Add from folder… card opens a native folder picker, so you can import a skill from anywhere.

Skills importer, discovery

3. Imported skills move to the top, each removable

Click a device card (or pick a folder) and it gets copied into screenpipe and shown under Imported, with a trash button to remove it.

Skills importer, after import

What happens when you import a skill

Import data flow

Note: the images above are faithful HTML mockups of the new components (same markup, Tailwind classes and theme tokens), rendered for this PR. Skill names are fictional, no real data.


How it works

  • Tauri commands. New src-tauri/src/skills.rs: scan_device_skills, list_imported_skills, import_skill, remove_imported_skill. Importing copies the SKILL.md folder into <data_dir>/skills/<name>/ (the store, the source of truth). Name normalization and frontmatter parsing are unit tested, and the baseline names (screenpipe-api, screenpipe-cli, screenpipe-team) are reserved and rejected.
  • Propagation. screenpipe-core PiExecutor::sync_user_skills mirrors the store into each pipe and chat session's .pi/skills/ on launch. So a skill imported once reaches the agent everywhere (chat plus every pipe, current and future) with no per-pipe wiring. Mirrored copies are tagged .screenpipe-managed, so removing a skill from the store self-cleans across sessions, while baseline and hand-authored skills are never touched. Best effort by design: a malformed skill is logged and skipped, it never blocks a session.
  • Frontend. SkillsCard modal plus a Skills spotlight and tile wired into connections-section.tsx; regenerated lib/utils/tauri.ts bindings.
~/.claude/skills/<name>/   --import-->   ~/.screenpipe/skills/<name>/   --sync each run-->   ~/.screenpipe/pi-chat/.pi/skills/
 (or any folder you pick)                 (store / source of truth)                          ~/.screenpipe/pipes/<pipe>/.pi/skills/

Testing

  • cargo test -p screenpipe-core: sync_user_skills mirror and self-clean test passes.
  • cargo test -p screenpipe-app: skill_key normalization and frontmatter-parse tests pass.
  • bun run bindings:check: no binding drift.
  • bun run build (next build): compiles and static exports, 15/15 pages.

Notes and possible follow-ups

  • Auto-scan currently covers ~/.claude/skills (plus the folder picker for anywhere else). Could extend to plugin skill dirs later.
  • Skills load at session start, so a new chat or pipe run picks up changes.

🤖 Generated with Claude Code

Add a "Skills" card to Settings → Connections (beside MCP servers).
"Connect skills" opens a modal that scans the device for SKILL.md
folders (~/.claude/skills, or any folder via a picker), and imports
the chosen ones into a screenpipe skills store.

- New Tauri commands (skills.rs): scan_device_skills, list_imported_skills,
  import_skill, remove_imported_skill — copy a SKILL.md folder into
  <data_dir>/skills/<name>/ and read it back. Name normalization +
  frontmatter parsing are unit-tested; reserved baseline names are guarded.
- screenpipe-core: PiExecutor::sync_user_skills mirrors the store into every
  pipe + chat session's .pi/skills/ on launch, so an imported skill reaches
  the agent everywhere with no per-pipe wiring. Mirrors are tagged
  .screenpipe-managed so removals self-clean; baseline + hand-authored
  skills are never touched. Best-effort: a bad skill never blocks a session.
  Added copy_dir_all helper + a sync unit test.
- Frontend: SkillsCard modal (imported list + device grid + "Add from
  folder…"), a Skills spotlight + tile in connections-section, regenerated
  tauri bindings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@louis030195

Copy link
Copy Markdown
Collaborator Author

@Anshgrover23 can u test?

@Anshgrover23

Copy link
Copy Markdown
Contributor

@louis030195 Tested working fine.

Screen.Recording.2026-06-06.at.2.46.40.AM.mov

E2E tests failing, unrelated to this PR.

@louis030195 louis030195 merged commit 782940a into main Jun 5, 2026
19 of 24 checks passed
louis030195 pushed a commit that referenced this pull request Jun 5, 2026
The device-skills import feature (#3869) shipped two unformatted test
lines in crates/screenpipe-core/src/agents/pi.rs, reddening the
Check formatting step on main. No logic change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
louis030195 pushed a commit that referenced this pull request Jun 6, 2026
CI clippy runs warn-only (-W clippy::all) so these never failed the
build but piled up. Cleared all 6 in screenpipe-core:

- sync.rs: gate the secrets-only helpers (connection_secret_key,
  oauth_secret_key, file_timestamp) and their prefix consts behind
  #[cfg(feature = "secrets")]. Every call site already lives in
  secrets-gated code, so default-feature builds (CI clippy, cargo test)
  saw them as dead. NOT deleted — --features secrets still needs them
  (verified: clippy clean under both feature sets).
- sync.rs tests: connection()'s `integration` param is vestigial
  (integration_id is derived from the key); rename to _integration.
- pi.rs: drop a needless &borrow in sync_user_skills_from.

Plus a hardening fix in the new skill-sync (device-skills import,
#3869): add BASELINE_SKILL_NAMES so a store entry named
screenpipe-api/-cli/-team can never be mirrored over the baseline skill
screenpipe writes itself (it would clobber it and, once marked managed,
get it deleted on a later sync). The desktop importer already rejects
these names; this is defense in depth. Test extended to cover it.

show.rs: #[allow(unused_variables)] on show_in_recording (consumed only
on Windows), matching the existing idiom at show_existing_main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants