InstallToApp writes the entity's content to the resolved location for app. For prompts/instructions: writes Content as a single file. For skills/agents/plugins: creates a directory named entity.Name containing a SKILL.md/AGENT.md/manifest.json — minimal but matches the Python tree shape.
(entity Entity, kind Kind, app string)
| 425 | // creates a directory named entity.Name containing a SKILL.md/AGENT.md/manifest.json |
| 426 | // — minimal but matches the Python tree shape. |
| 427 | func InstallToApp(entity Entity, kind Kind, app string) (string, error) { |
| 428 | apps := AppPathsFor(kind) |
| 429 | dest, ok := apps[app] |
| 430 | if !ok { |
| 431 | return "", fmt.Errorf("entities: app %s does not support %s", app, kind) |
| 432 | } |
| 433 | resolved := pathutil.Expand(dest) |
| 434 | if err := os.MkdirAll(filepath.Dir(resolved), 0o755); err != nil { |
| 435 | return "", err |
| 436 | } |
| 437 | switch kind { |
| 438 | case KindPrompt, KindInstruction: |
| 439 | return resolved, writeFile(resolved, []byte(entity.Content), 0o600) |
| 440 | default: |
| 441 | dir := filepath.Join(resolved, entity.Name) |
| 442 | if err := os.MkdirAll(dir, 0o755); err != nil { |
| 443 | return "", err |
| 444 | } |
| 445 | switch kind { |
| 446 | case KindSkill: |
| 447 | path := filepath.Join(dir, "SKILL.md") |
| 448 | return dir, writeFile(path, []byte(entity.Content), 0o600) |
| 449 | case KindAgent: |
| 450 | path := filepath.Join(dir, "AGENT.md") |
| 451 | return dir, writeFile(path, []byte(entity.Content), 0o600) |
| 452 | case KindPlugin: |
| 453 | path := filepath.Join(dir, "manifest.json") |
| 454 | content := entity.Content |
| 455 | if strings.TrimSpace(content) == "" { |
| 456 | content = "{}\n" |
| 457 | } |
| 458 | return dir, writeFile(path, []byte(content), 0o600) |
| 459 | } |
| 460 | } |
| 461 | return resolved, nil |
| 462 | } |
| 463 | |
| 464 | // UninstallFromApp removes the entity's installation for app and reports |
| 465 | // whether anything was removed. |