Data model
config.json (schema v1)
Stored at ~/.ide-agents/config.json:
{
"version": 1,
"adapter": "cursor",
"ides": {
"opencode": { "enabled": true, "configPath": "/Users/me/.config/opencode" },
"cursor": { "enabled": true, "configPath": "/Users/me/.cursor" },
"claude": { "enabled": true, "configPath": "/Users/me/.claude" },
"codex": { "enabled": false, "configPath": "/Users/me/.codex" }
},
"server": { "port": 3921 },
"repos": [
{
"id": "main",
"url": "https://github.com/org/skills.git",
"ref": "main",
"slug": "github-com-org-skills"
}
],
"installations": [
{
"id": "uuid",
"repoId": "main",
"kind": "skill",
"artifactId": "tech-debt",
"sourcePath": "skills/tech-debt",
"targetName": "tech-debt",
"global": false,
"project": true,
"projectPath": "/Users/me/code/my-app"
}
],
"recentProjects": ["/Users/me/code/my-app"]
}
ides
Per-tool settings — see Settings & IDEs.
| Field | Description |
|---|---|
enabled | If true, apply creates symlinks for this tool |
configPath | Global config directory (default ~/.config/opencode, ~/.cursor, ~/.claude, or ~/.codex) |
On first config creation, enabled is set only when the matching directory already exists under ~.
Installation fields
| Field | Description |
|---|---|
kind | "skill" or "agent" |
global | Symlink under each enabled tool’s configPath |
project | Symlink under <project>/<tool-subfolder>/... |
projectPath | Active installs use CLI launch cwd; when project is off, the previous path is kept so removal can run |
Global and project are independent in the UI — both may be active for the same artifact (global symlink in IDE config dirs, project symlink under the launch directory). A single installation record is applied to all enabled IDEs when you toggle either scope.
recentProjects
| Field | Description |
|---|---|
recentProjects | Up to 10 absolute paths, most recent first. Updated when a project install is saved via PUT /installations. |
Repository scan: skillLayout
Each repo in GET /api/repos includes a detected layout (not stored in config.json):
| Value | Meaning |
|---|---|
nested | skills/<id>/SKILL.md |
bucketed | skills/<bucket>/<id>/SKILL.md |
flat | <id>/SKILL.md at repo root |
empty | No skills found |
Detection order: nested → bucketed → flat. See Source repositories.
Legacy migration
scope: "global" | "project" | "off"→global/projectbooleans- Configs without
ides→ defaults from home-folder detection adapterkept for compatibility (first enabled IDE)
Artifact (scanned, not persisted)
Returned by GET /api/repos/:id/artifacts:
{
"id": "hello",
"kind": "skill",
"sourcePath": "skills/hello",
"name": "hello",
"description": "From SKILL.md frontmatter",
"allowedScope": "any",
"bucket": ".curated",
"codexMeta": {
"displayName": "Hello",
"shortDescription": "Demo skill from the starter template.",
"defaultPrompt": "Say hello using this skill."
},
"targets": {
"global": { "exists": false, "isSymlink": false, "blocked": false },
"project": { "exists": true, "isSymlink": true, "blocked": false }
}
}
For agents, optional dependsOnSkills lists skill ids from frontmatter; GET /artifacts also resolves skillDependencies with names and descriptions for the UI. Router agents may also declare dependsOnSubagents (other agent ids they delegate to); ide-agents resolves it into subagentDependencies and, on install, transitively enables the delegated agents and their own skills. A subagent cannot be turned off while a router agent that depends on it is installed in the same scope.
allowedScope comes from SKILL.md or agent frontmatter. If missing, it defaults to any (both toggles enabled).
bucket is set only for bucketed layouts. codexMeta is parsed from agents/openai.yaml when present (presentation only).
targets aggregates status across all enabled IDEs: blocked if any tool has a non-symlink at the target path.