Remote Skill Sources

Share skills from a central git repo — every project stays in sync automatically

Point agents at a git URL — every project picks up the latest skills without a manual install.

Diagram

Remote Skill Sources

🔗 Git URL

⚙️ skills sync

💾 Versioned Cache
~/.praisonai/cache/remote-skills

🤖 Every Agent

Quick Start

  1. Sync from the CLI

    Pull the latest skills and cache them locally. Every agent on this machine picks them up automatically — no code change needed.

    bash
    # Pull the latest and cache it locally
    praisonai skills sync https://github.com/acme/team-skills
    
    # Pin to a branch / tag / commit for reproducible builds
    praisonai skills sync https://github.com/acme/team-skills --ref v1.2.0
  2. Declare once, sync bare

    Add sources to your project praisonai.yaml, then run sync with no arguments:

    yaml
    skills:
      urls:
        - https://github.com/acme/team-skills
        - url: https://github.com/acme/internal-runbooks
          ref: main
    bash
    praisonai skills sync

    sync reads skills.urls (or the alias skills.sources) from the project’s praisonai.yaml/praisonai.yml first, then falls back to the user-global ~/.praisonai/config.yaml.

  3. From Python

    Pass a git URL to sources= and discovery fetches, caches, and validates it:

    python
    from praisonaiagents import Agent
    from praisonaiagents.skills import discover_skills
    
    skills = discover_skills(sources=["https://github.com/acme/team-skills"])
    
    agent = Agent(
        name="Reviewer",
        instructions="You review pull requests using our team's shared skills.",
        skills=[str(s.path) for s in skills],
    )
    
    agent.start("Review PR #42")

How It Works

Sync shallow-clones the repo (with GIT_TERMINAL_PROMPT=0 so a credential prompt cannot hang it), resolves the commit, atomically swaps it into a versioned cache, and points current at it. Each git call has a 120-second deadline. If git fails or stalls, the last-good current alias is returned so agents keep working offline.

Diagram
Agent~/.praisonai/cache/remote-skillsGit Remotepraisonai skills syncUserAgent~/.praisonai/cache/remote-skillsGit Remotepraisonai skills syncUseralt[Success][Stalled remote (120s deadline)][Network failure]praisonai skills sync <url>shallow clone –depth=1repo treeresolve commit SHAatomic swap into versioned dirpoint `current` -> new versionfall back to last-good `current`fall back to last-good `current`discover_skills() scans `current`fresh skills used immediately
StepWhat happens
FetchShallow git clone into a temp dir
VersionResolved commit SHA becomes the cache version dir
SwapAtomic rename + current symlink (falls back to copy on symlink-less filesystems)
PruneOld versioned dirs removed, current kept
DeadlineEach git call times out after 120 s, with GIT_TERMINAL_PROMPT=0
OfflineIf clone fails or times out, current from the last good sync is used

Configuration Options

Two YAML shapes are supported — pick either. skills.sources is an alias for skills.urls.

yaml
# String form
skills:
  urls:
    - https://github.com/acme/team-skills

# Dict form with ref pinning
skills:
  urls:
    - url: https://github.com/acme/team-skills
      ref: v1.2.0

When both project and user config define sources, project entries win and are listed first; duplicates are removed while order is preserved.

CLI — praisonai skills sync:

OptionTypeDefaultDescription
URL (positional)str(from config)Remote skill source git URL. If omitted, uses skills.urls from config.
--ref / -rstrNonePin a branch / tag / commit for reproducible syncs.

Python API:

SymbolSignaturePurpose
GitRemoteSkillSource(url: str, ref: Optional[str] = None)Default git-backed source implementation
fetch_remote_skill_dirs(sources, cache_dir: Optional[Path] = None) -> List[Path]Fetch all sources; returns validated cache dirs
discover_skills(skill_dirs=None, include_defaults=True, sources: Optional[List] = None)sources= kwarg; remote sources scanned after local dirs

sources items may be a URL str, a {"url": ..., "ref": ...} dict, or any object with a .fetch(cache_dir) -> List[Path] method.


Which entry point should I use?

Diagram

One-off from CLI

Shared team config

Programmatic

Just want it to work

How are you
using skills?

praisonai skills sync URL

Add to praisonai.yaml
then: praisonai skills sync

discover_skills sources=…

Any of the above —
agents auto-pick up cache


Team Workflow

This feature shines for teams: one lead pushes a skill, everyone syncs.

Diagram
AgentEvery DeveloperCentral Git RepoTeam LeadAgentEvery DeveloperCentral Git RepoTeam LeadPush new skill (SKILL.md)praisonai skills syncshallow cloneSKILL.md filescache under ~/.praisonai/cache/remote-skillsdiscover_skills() picks up new skilluses updated skill immediately

Common Patterns

Pin for reproducible builds

Always pass a ref in CI so builds don’t drift onto an upstream commit.

bash
praisonai skills sync https://github.com/acme/team-skills --ref v1.2.0

Local-wins layering

Put per-project overrides in ./.praisonai/skills/. The remote cache is lowest precedence, so a local skill with the same name always wins a collision.

Offline-first

The last-good cache is served automatically on any network failure or stalled remote — no code change needed.


Best Practices

Pin refs in CI, float in dev

Pin --ref v1.2.0 in CI for reproducible builds; drop the ref in local dev for easy iteration on the latest.

Treat remote content as untrusted

The parser re-validates every synced skill before it reaches a prompt. Don’t disable validation, and review the source repo before adding it.

One repo, many skills

A remote repo can hold a single SKILL.md at its root (one skill) or many subdirectories each with a SKILL.md. Both layouts are handled and de-duplicated by discovery.

skills add / install vs skills sync

add and install are the same one-shot copy — pick whichever verb reads more naturally (add mirrors the familiar npx skills add <url>). sync keeps a versioned cache and refreshes on demand. Use sync for shared team libraries.


Related