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

# agentx source

> Add the git repositories you install skills from, fetch them again, list their skills, and remove them.

A source is a git repository that holds one or more skills. Add it by URL once; agentx fetches it into its own store and lists the skills inside, so you can pick what to install. [`agentx skill add`](/cli/skill) adds the source itself when you install from a URL you have not added yet.

## Add a source

```sh theme={null}
agentx source add anthropics/skills
```

```text theme={null}
✓ added https://github.com/anthropics/skills at 3f2a9c1: 12 skills
```

Paste the URL in whatever form you have:

| Form | Example |
| - | - |
| GitHub shorthand | `owner/repo`, `owner/repo/skills` |
| GitHub URL | `https://github.com/owner/repo`, `https://github.com/owner/repo/tree/main/skills` |
| GitLab URL | `https://gitlab.com/group/repo`, `https://gitlab.com/group/repo/-/tree/main/skills` |
| SSH | `git@github.com:owner/repo.git`, `ssh://git@github.com/owner/repo` |
| Any git server | `https://git.example.com/team/repo.git/skills` |
| Local repository | `file:///srv/skills.git` |

Add `#<ref>` to pin the source to a branch, a tag or a commit, for example `owner/repo#v2` or `git@github.com:owner/repo.git#release`. Without a pin the source follows the repository's default branch. A `tree` URL pins the branch it names.

A path after the repository, such as `owner/repo/skills`, scopes the listing to that directory. On a server other than GitHub, end the repository name with `.git` so agentx knows where the repository ends and the path begins. The path must name a directory by its plain names: `.`, `..` and `.git` are refused, however they are written.

Adding a source you already have fetches it again and sets the pin to what you typed this time. The confirmation then tells you what moved:

```text theme={null}
✓ re-fetched https://github.com/anthropics/skills, now at 9c1d0ab, was 3f2a9c1: 12 skills
✓ re-fetched https://github.com/anthropics/skills, already at 9c1d0ab: 12 skills
```

### Credentials

The fetch runs with your own git, so the credential helper, SSH key and URL rewrites you use in a terminal apply here too. A private repository you can already clone just works.

Never put a token in the URL. agentx drops it before the URL is used anywhere, and never repeats it back to you, not even in an error. For an SSH URL the `git@` part is the address rather than a credential, so it is kept and only a password is dropped. If the fetch then fails, store the credential in a git credential helper instead:

```sh theme={null}
git config --global credential.helper store
```

### What is fetched

agentx fetches only the commits and directory trees of one branch, no tags and no file contents, then the `SKILL.md` file of every skill in the repository in one round trip. Those come down whatever path you added, so listing any part of the source afterwards needs no network. A source the size of a monorepo costs a few megabytes, not a clone. A git server that cannot serve such a partial fetch gets a full one instead; nothing changes for you.

A fetch lands whole or not at all. agentx fills its copy in two round trips and moves the source to the new commit only once everything has arrived, so a fetch that fails, whether from a dropped connection, a Ctrl-C or a machine that goes down, leaves the source exactly as it was. Listing and searching keep working at the last version that arrived complete. Fetch again to pick it up.

### A failed add leaves nothing behind

An add undoes itself when it cannot finish. agentx registers the repository with its own git store before it fetches, and takes that registration back if the fetch fails or if the source cannot be recorded. A source is on this machine whole or not at all, so `source list` never hides one.

Taking it back needs the same lock every agentx command takes, so an add that fails while another command is running waits a few seconds for that command. If the other command outlasts the wait, the add names what it left:

```text theme={null}
error: another agentx command holds the lock; the remote src-1c9d0b7e4a2f6d38 was left in the account repo and no source names it
hint: run 'agentx source add https://github.com/anthropics/skills' to add the source and take the remote with it, or 'agentx source remove 1c9d0b7e4a2f6d38' to clear it
```

Run either command in the hint. Adding the source again finishes the job; removing it by id clears the leftover.

## Fetch a source again

```sh theme={null}
agentx source fetch anthropics/skills
```

```text theme={null}
✓ re-fetched https://github.com/anthropics/skills, now at 9c1d0ab, was 3f2a9c1: 13 skills
```

A fetch updates what agentx knows about a source: the commit it holds and the skills inside it. Run it when you want to see what changed upstream now. [`agentx skill check`](/cli/skill#check-for-updates) fetches the sources your managed skills came from on its own, and while the desktop app is open, its [background process](/cli/serve#update-checks) fetches every source you added when it starts and every thirty minutes, including the ones you have not installed anything from yet.

Name several sources to fetch them together, by URL or by id, or fetch every source on this machine:

```sh theme={null}
agentx source fetch anthropics/skills 7a3b5c9e1f2d4a60
agentx source fetch --all
```

Sources are fetched in parallel, a few at a time, and each one gets a line that says what moved:

```text theme={null}
✓ re-fetched https://github.com/anthropics/skills, now at 9c1d0ab, was 3f2a9c1: 13 skills
✓ re-fetched https://github.com/me/skills, already at 8b1e0f4: 4 skills
```

A source that fails is a warning naming it and does not stop the others. Every source that did fetch is recorded, and the command then fails, naming the ones that did not. Its exit code is the one they agree on, which is the code you would get fetching that source on its own, or `3` when they failed for different reasons.

A fetch keeps the pin the source has. To change it, add the source again with the ref you want:

```sh theme={null}
agentx source add anthropics/skills#v2
```

A path in the URL is ignored here: a fetch always covers the whole source.

## List your sources

```sh theme={null}
agentx source list
```

```text theme={null}
2 sources
  https://github.com/anthropics/skills  (unpinned)  3f2a9c1  2026-09-20T10:00:00Z  1c9d0b7e4a2f6d38
  https://github.com/me/skills          v2          8b1e0f4  2026-09-19T18:30:00Z  7a3b5c9e1f2d4a60
```

Each row shows the canonical URL, the pin, the fetched commit, when it was last fetched and the source id. The id is accepted wherever a URL is.

## List the skills of a source

```sh theme={null}
agentx source skills anthropics/skills
```

```text theme={null}
12 skills in https://github.com/anthropics/skills at 3f2a9c1
  docx            skills/docx            Create and edit Word documents
  pdf             skills/pdf             Read, merge and fill PDF files
  ...
```

Every directory with a `SKILL.md` is a skill. Hidden directories and `node_modules` are skipped. Names and descriptions come from the repository, so agentx prints them with control characters replaced by spaces, keeping one skill to a row; `--json` gives you the value as it was written. Give a path to see one part of the repository, for example `anthropics/skills/skills/pdf`, or the source id instead of the URL. The command reads what the last `source add` fetched and never touches the network, whichever part of the source you ask for.

## Remove a source

```sh theme={null}
agentx source remove anthropics/skills
```

```text theme={null}
✓ removed https://github.com/anthropics/skills
```

The source and everything fetched from it leave this machine. Skills you installed from it stay as they are, in your library and in your clients, and keep their record of where they came from.

`agentx skill list` shows each of those skills as `source removed`, and the snapshot the desktop app reads says the same:

```text theme={null}
1 skill
  pdf  managed  current, source removed  https://github.com/anthropics/skills/skills/pdf  4 placements
```

Add the source again to fetch it anew and clear the state:

```sh theme={null}
agentx source add anthropics/skills
```

Nothing else changes: the skills, their records and their placements are exactly as they were before you removed the source. Any pin works, since a source is identified by its URL. Installing a skill from the source by its URL, or adopting one with [`agentx adopt`](/cli/adopt), adds it again too.

A command that names the removed source by its id cannot fetch it, since an id is not a URL. While a skill still records the source, the command tells you what to run instead:

```text theme={null}
error: no source with id 1c9d0b7e4a2f6d38: https://github.com/anthropics/skills was removed, and the skills installed from it still name it
hint: run 'agentx source add https://github.com/anthropics/skills' to add it again
```

Once you take the last of those skills off the machine, with [`agentx skill remove <name>`](/cli/skill) or its `--from universal` form, nothing on this machine records the source's URL any more, and the id is refused like any other. Add the source again by its URL.

## Script it

Add `--json` to get a `source` event per source, and from `source skills` a `source_skill` event per skill:

```sh theme={null}
agentx --json source skills anthropics/skills
```

```json theme={null}
{"type":"source","schema_version":1,"id":"1c9d0b7e4a2f6d38","url":"https://github.com/anthropics/skills","last_fetched":"2026-09-20T10:00:00Z","commit":"3f2a9c1e...","skills":12}
{"type":"source_skill","schema_version":1,"source":"1c9d0b7e4a2f6d38","subpath":"skills/docx","name":"docx","description":"Create and edit Word documents","tree":"9a8b7c6d..."}
{"type":"result","schema_version":1,"ok":true}
```

`source fetch` emits one `progress` event per source as that source finishes, then one `source` event per source that fetched, in the order you named them. A `source` event carries `previous_commit` when the fetch moved the source, so a script can tell a real change from a no-op:

```json theme={null}
{"type":"progress","schema_version":1,"phase":"fetch","subject":"https://github.com/anthropics/skills","current":1,"total":2}
{"type":"source","schema_version":1,"id":"1c9d0b7e4a2f6d38","url":"https://github.com/anthropics/skills","last_fetched":"2026-09-21T09:00:00Z","commit":"9c1d0ab...","previous_commit":"3f2a9c1...","skills":13}
```

## Exit codes

* `1`: the URL is not one of the accepted forms, the pin and the tree URL name different refs, or `source fetch` was given neither a source nor `--all`.
* `3`: the source cannot be reached, is not a git repository, or needs credentials git does not have. The hint names the fix. From `source fetch` over several sources, it also means they failed for different reasons; read the warnings.
* `5`: the pinned ref or the path does not exist in the source, the source is not on this machine, or what this machine holds of it is incomplete. For an id of a source you removed, the hint names the `agentx source add` command that brings it back.
* `7`: another agentx command is running. Retry when it finishes. An add that could not take its own half-done work back says what it left and how to clear it.
* `8`: the account repo in agentx home cannot be read or written. Run `agentx doctor`.

Each code means the same thing from every `source` command: fetching one source answers exactly as adding or listing it would.


## Related topics

- [agentx serve](/cli/serve.md)
- [agentx skill](/cli/skill.md)
- [agentx export and import](/cli/export.md)
- [agentx adopt](/cli/adopt.md)
- [agentx doctor](/cli/doctor.md)
