> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Remote Skill Sources"
        URL[🔗 Git URL] --> Sync[⚙️ skills sync]
        Sync --> Cache[💾 Versioned Cache<br/>~/.praisonai/cache/remote-skills]
        Cache --> Agent[🤖 Every Agent]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class URL input
    class Sync,Cache process
    class Agent output
```

## 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
skills:
  urls:
    - https://github.com/acme/team-skills
    - url: https://github.com/acme/internal-runbooks
      ref: main
```

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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")
```

> [!NOTE]
>
> Backward compatible: without `sources=`, `skills.urls`, or an explicit `sync`, nothing changes.

***

## 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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant CLI as praisonai skills sync
    participant Git as Git Remote
    participant Cache as ~/.praisonai/cache/remote-skills
    participant Agent

    User->>CLI: praisonai skills sync <url>
    CLI->>Git: shallow clone --depth=1
    alt Success
        Git-->>CLI: repo tree
        CLI->>CLI: resolve commit SHA
        CLI->>Cache: atomic swap into versioned dir
        CLI->>Cache: point `current` -> new version
    else Stalled remote (120s deadline)
        CLI-->>Cache: fall back to last-good `current`
    else Network failure
        CLI-->>Cache: fall back to last-good `current`
    end
    Agent->>Cache: discover_skills() scans `current`
    Cache-->>Agent: fresh skills used immediately
```

| Step | What happens |
| - | - |
| Fetch | Shallow git clone into a temp dir |
| Version | Resolved commit SHA becomes the cache version dir |
| Swap | Atomic rename + `current` symlink (falls back to copy on symlink-less filesystems) |
| Prune | Old versioned dirs removed, `current` kept |
| Deadline | Each `git` call times out after 120 s, with `GIT_TERMINAL_PROMPT=0` |
| Offline | If 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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`:**

| Option | Type | Default | Description |
| - | - | - | - |
| `URL` (positional) | `str` | *(from config)* | Remote skill source git URL. If omitted, uses `skills.urls` from config. |
| `--ref` / `-r` | `str` | `None` | Pin a branch / tag / commit for reproducible syncs. |

**Python API:**

| Symbol | Signature | Purpose |
| - | - | - |
| `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?

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{How are you<br/>using skills?} -->|One-off from CLI| A[praisonai skills sync URL]
    Q -->|Shared team config| B[Add to praisonai.yaml<br/>then: praisonai skills sync]
    Q -->|Programmatic| C[discover_skills sources=...]
    Q -->|Just want it to work| D[Any of the above —<br/>agents auto-pick up cache]

    classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef path fill:#189AB4,stroke:#7C90A0,color:#fff

    class Q q
    class A,B,C,D path
```

***

## Team Workflow

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

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Lead as Team Lead
    participant Repo as Central Git Repo
    participant Dev as Every Developer
    participant Agent as Agent

    Lead->>Repo: Push new skill (SKILL.md)
    Dev->>Dev: praisonai skills sync
    Dev-->>Repo: shallow clone
    Repo-->>Dev: SKILL.md files
    Dev->>Dev: cache under ~/.praisonai/cache/remote-skills
    Agent->>Agent: discover_skills() picks up new skill
    Agent-->>Dev: uses 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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.

> [!WARNING]
>
> On a first run (empty cache) with an unreachable or stalled remote, the source returns no skills and a warning is logged. The agent still starts — run `praisonai skills sync` once the network is available.

***

## Best Practices

> [accordion] 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.

> [accordion] 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.

> [accordion] 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.

> [accordion] 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

> [card] [Skill Invocation](https://praison.ai/docs/features/skills-invocation.md)
>
> How agents actually run a skill — slash commands and argument substitution

> [card] [Skills](https://praison.ai/docs/concepts/skills.md)
>
> The underlying Skill concept — author and load SKILL.md files


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.