gaia-cli 4.2.1__tar.gz → 4.3.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. {gaia_cli-4.2.1/src/gaia_cli.egg-info → gaia_cli-4.3.6}/PKG-INFO +18 -24
  2. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/README.md +17 -23
  3. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/pyproject.toml +1 -1
  4. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/cardRenderer.py +14 -0
  5. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/commands/stats.py +3 -1
  6. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/graph.py +1 -1
  7. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/main.py +32 -20
  8. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/pathEngine.py +6 -1
  9. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/prWriter.py +5 -0
  10. {gaia_cli-4.2.1 → gaia_cli-4.3.6/src/gaia_cli.egg-info}/PKG-INFO +18 -24
  11. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_card_renderer.py +27 -0
  12. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_dx.py +22 -0
  13. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_intake.py +2 -1
  14. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_path_command.py +8 -8
  15. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_push.py +2 -2
  16. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_stats.py +20 -0
  17. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_validate.py +41 -1
  18. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/LICENSE +0 -0
  19. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/setup.cfg +0 -0
  20. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/__init__.py +0 -0
  21. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/__main__.py +0 -0
  22. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/authz.py +0 -0
  23. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/combinator.py +0 -0
  24. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/commands/__init__.py +0 -0
  25. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/commands/dev.py +0 -0
  26. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/gaia.json +0 -0
  27. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/named/devin-ai/autonomous-swe.md +0 -0
  28. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/named/karpathy/autoresearch.md +0 -0
  29. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/named-skills.json +0 -0
  30. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/combination.schema.json +0 -0
  31. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/meta.json +0 -0
  32. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/namedSkill.schema.json +0 -0
  33. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/pluginConfig.schema.json +0 -0
  34. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/realSkillCatalog.schema.json +0 -0
  35. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/skill.schema.json +0 -0
  36. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/skillBatch.schema.json +0 -0
  37. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/skillSuite.schema.json +0 -0
  38. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/data/registry/schema/skillTree.schema.json +0 -0
  39. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/embeddings.py +0 -0
  40. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/evidence.py +0 -0
  41. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/formatting.py +0 -0
  42. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/hook.py +0 -0
  43. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/install.py +0 -0
  44. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/interactive.py +0 -0
  45. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/leveling.py +0 -0
  46. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/localContext.py +0 -0
  47. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/name.py +0 -0
  48. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/promotion.py +0 -0
  49. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/push.py +0 -0
  50. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/redaction.py +0 -0
  51. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/registry.py +0 -0
  52. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/resolver.py +0 -0
  53. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/scanner.py +0 -0
  54. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/semantic_search.py +0 -0
  55. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/timeline.py +0 -0
  56. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/treeManager.py +0 -0
  57. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/__init__.py +0 -0
  58. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/app.py +0 -0
  59. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/screens/__init__.py +0 -0
  60. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/screens/agent.py +0 -0
  61. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/screens/hero.py +0 -0
  62. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/screens/levelup.py +0 -0
  63. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/screens/scan.py +0 -0
  64. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/screens/tree.py +0 -0
  65. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/theme.tcss +0 -0
  66. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/tui/tokens.py +0 -0
  67. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli/versioning.py +0 -0
  68. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli.egg-info/SOURCES.txt +0 -0
  69. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli.egg-info/dependency_links.txt +0 -0
  70. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli.egg-info/entry_points.txt +0 -0
  71. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli.egg-info/requires.txt +0 -0
  72. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/src/gaia_cli.egg-info/top_level.txt +0 -0
  73. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_authz.py +0 -0
  74. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_crawlers.py +0 -0
  75. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_docs_site.py +0 -0
  76. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_docs_skill_explorer.py +0 -0
  77. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_embeddings.py +0 -0
  78. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_evidence_inheritance.py +0 -0
  79. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_formatting.py +0 -0
  80. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_graph.py +0 -0
  81. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_install.py +0 -0
  82. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_interactive.py +0 -0
  83. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_leveling.py +0 -0
  84. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_lifecycle.py +0 -0
  85. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_local_context.py +0 -0
  86. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_meta_ops.py +0 -0
  87. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_named_skills.py +0 -0
  88. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_packaging.py +0 -0
  89. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_path_engine.py +0 -0
  90. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_pr540_review.py +0 -0
  91. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_pr_writer.py +0 -0
  92. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_promotion.py +0 -0
  93. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_real_skill_catalog.py +0 -0
  94. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_redaction.py +0 -0
  95. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_registry_layout.py +0 -0
  96. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_scanner.py +0 -0
  97. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_suite_install.py +0 -0
  98. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_timelines.py +0 -0
  99. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_treeManager.py +0 -0
  100. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_tui_tokens.py +0 -0
  101. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_unlocked_at_datetime.py +0 -0
  102. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_verify_evidence.py +0 -0
  103. {gaia_cli-4.2.1 → gaia_cli-4.3.6}/tests/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gaia-cli
3
- Version: 4.2.1
3
+ Version: 4.3.6
4
4
  Summary: Gaia AI Agent Skill Registry CLI
5
5
  Author: Gaia contributors
6
6
  License: MIT
@@ -54,20 +54,18 @@ Dynamic: license-file
54
54
  </picture>
55
55
  </div>
56
56
 
57
- # Gaia - AI Agent Skill Registry
57
+ # Gaia - This is not a skill marketplace
58
58
 
59
- > The open, evidence-backed skill graph for AI agents: collect, evolve, and fuse capabilities into something legendary.
59
+ > This is an open, evidence-backed skill graph. The game is to name a skill to your repository--the best skill takes "origin".
60
60
  > Success means becoming the public record AI agent developers cite when making capability claims — the pkg.go.dev for agent skills.
61
61
 
62
- ### New here? Read [META.md](META.md) first
62
+ ### How does ranking work? Read [META.md](META.md) for a comprehensive list
63
63
 
64
64
  [![Validate](https://github.com/mbtiongson1/gaia-skill-tree/actions/workflows/validate.yml/badge.svg)](https://github.com/mbtiongson1/gaia-skill-tree/actions/workflows/validate.yml)
65
65
  [![License: MIT](https://img.shields.io/badge/License-MIT-c084fc.svg)](LICENSE)
66
66
  [![Website](https://img.shields.io/badge/Website-gaia.tiongson.co-f59e0b)](https://gaia.tiongson.co/)
67
67
 
68
- # NEW! Badges
69
-
70
- Have a named skill? Get yours now! Should look like this:
68
+ # Name a skill, get a badge.
71
69
 
72
70
  [![Gaia](https://gaia.tiongson.co/badges/_assets/mbtiongson1/gaia-curate.svg?repo=mbtiongson1%2Fgaia-skill-tree)](https://gaia.tiongson.co/u/mbtiongson1/)<br>
73
71
  [![Gaia rank](https://gaia.tiongson.co/badges/_assets/mbtiongson1/rank.svg?repo=mbtiongson1%2Fgaia-skill-tree)](https://gaia.tiongson.co/u/mbtiongson1/)<br>
@@ -81,9 +79,15 @@ Generate yours at **[gaia.tiongson.co/badges/](https://gaia.tiongson.co/badges/)
81
79
 
82
80
  ---
83
81
 
84
- ## The Registry
82
+ # Who maintains this?
83
+
84
+ Truth is, Gaia will exist even without anyone sending their skills.
85
+
86
+ I built this because skills should be attributed to the people who proved them. Permanently, not just until the repo goes private.
85
87
 
86
- Every AI agent capability exists somewhere on this graph. Skills start at the foundation tier, awaken through evidence, evolve through use, and fuse into things greater than the sum of their parts.
88
+ So that means, its the developers who make skills maintaining this. I have a thorough curation process, and the dev community is evidence on why this works. As long as developers making skills exists, this registry will exist. This is open-source, so feel free to contribute!
89
+
90
+ # The Skill Tree
87
91
 
88
92
  <!-- gaia:registry-start -->
89
93
  ```text
@@ -163,7 +167,7 @@ Skills rank up through **verifiable evidence** (Class A/B/C) and can be demoted
163
167
  **1. Install the CLI**
164
168
 
165
169
  <!-- gaia:version-start -->
166
- Current Gaia CLI version: `4.2.0`.
170
+ Current Gaia CLI version: `4.3.6`.
167
171
 
168
172
  ```bash
169
173
  curl -fsSL https://gaia.tiongson.co/install.sh | sh
@@ -179,17 +183,7 @@ npm install -g @gaia-registry/cli
179
183
  Requires Python 3.8+. The script prefers `pipx` if available, otherwise falls back to `pip install --user` and prints a PATH hint if needed.
180
184
 
181
185
  <details>
182
- <summary>pip / npm / pipx / Windows alternatives</summary>
183
-
184
- **pip (Python):**
185
- ```bash
186
- pip install gaia-cli
187
- ```
188
-
189
- **npm wrapper:**
190
- ```bash
191
- npm install -g @gaia-registry/cli
192
- ```
186
+ <summary>pipx / Windows alternatives</summary>
193
187
 
194
188
  **pipx:**
195
189
  ```bash
@@ -207,7 +201,7 @@ $env:PATH += ";" + (python -c "import sysconfig; print(sysconfig.get_path('scrip
207
201
  ```bash
208
202
  git clone https://github.com/mbtiongson1/gaia-skill-tree.git
209
203
  cd gaia-skill-tree
210
- pip install -e ".[embeddings,dev]"
204
+ pip install -e ".[embeddings,dev,docs]"
211
205
  ```
212
206
 
213
207
  The `dev` extra installs packaging/test tools such as `build` and `pytest`; without it,
@@ -426,9 +420,9 @@ Thank you to everyone who has expanded the Gaia registry.
426
420
  | [@rico-tiongson](https://github.com/rico-tiongson) | Collaborator: early feature contributions and ongoing pair programming |
427
421
  | [@Juno](https://github.com/Juno) | Key contributor: graph browser expansion, function-calling skill, RAG pipeline evidence, and CLI DX improvements |
428
422
 
429
- ### Named Skill Contributors
423
+ ### Named Skills
430
424
 
431
- | Contributor | Skills |
425
+ | Developers | Skills |
432
426
  |---|---|
433
427
  | [@ruvnet](https://github.com/ruvnet) | 48 — agentdb, flow-nexus, hive-mind-coordination, browser, and 44 others |
434
428
  | [@garrytan](https://github.com/garrytan) | 47 — gstack ecosystem: browse, qa, ship, review, benchmark, learn, and 41 others |
@@ -5,20 +5,18 @@
5
5
  </picture>
6
6
  </div>
7
7
 
8
- # Gaia - AI Agent Skill Registry
8
+ # Gaia - This is not a skill marketplace
9
9
 
10
- > The open, evidence-backed skill graph for AI agents: collect, evolve, and fuse capabilities into something legendary.
10
+ > This is an open, evidence-backed skill graph. The game is to name a skill to your repository--the best skill takes "origin".
11
11
  > Success means becoming the public record AI agent developers cite when making capability claims — the pkg.go.dev for agent skills.
12
12
 
13
- ### New here? Read [META.md](META.md) first
13
+ ### How does ranking work? Read [META.md](META.md) for a comprehensive list
14
14
 
15
15
  [![Validate](https://github.com/mbtiongson1/gaia-skill-tree/actions/workflows/validate.yml/badge.svg)](https://github.com/mbtiongson1/gaia-skill-tree/actions/workflows/validate.yml)
16
16
  [![License: MIT](https://img.shields.io/badge/License-MIT-c084fc.svg)](LICENSE)
17
17
  [![Website](https://img.shields.io/badge/Website-gaia.tiongson.co-f59e0b)](https://gaia.tiongson.co/)
18
18
 
19
- # NEW! Badges
20
-
21
- Have a named skill? Get yours now! Should look like this:
19
+ # Name a skill, get a badge.
22
20
 
23
21
  [![Gaia](https://gaia.tiongson.co/badges/_assets/mbtiongson1/gaia-curate.svg?repo=mbtiongson1%2Fgaia-skill-tree)](https://gaia.tiongson.co/u/mbtiongson1/)<br>
24
22
  [![Gaia rank](https://gaia.tiongson.co/badges/_assets/mbtiongson1/rank.svg?repo=mbtiongson1%2Fgaia-skill-tree)](https://gaia.tiongson.co/u/mbtiongson1/)<br>
@@ -32,9 +30,15 @@ Generate yours at **[gaia.tiongson.co/badges/](https://gaia.tiongson.co/badges/)
32
30
 
33
31
  ---
34
32
 
35
- ## The Registry
33
+ # Who maintains this?
34
+
35
+ Truth is, Gaia will exist even without anyone sending their skills.
36
+
37
+ I built this because skills should be attributed to the people who proved them. Permanently, not just until the repo goes private.
36
38
 
37
- Every AI agent capability exists somewhere on this graph. Skills start at the foundation tier, awaken through evidence, evolve through use, and fuse into things greater than the sum of their parts.
39
+ So that means, its the developers who make skills maintaining this. I have a thorough curation process, and the dev community is evidence on why this works. As long as developers making skills exists, this registry will exist. This is open-source, so feel free to contribute!
40
+
41
+ # The Skill Tree
38
42
 
39
43
  <!-- gaia:registry-start -->
40
44
  ```text
@@ -114,7 +118,7 @@ Skills rank up through **verifiable evidence** (Class A/B/C) and can be demoted
114
118
  **1. Install the CLI**
115
119
 
116
120
  <!-- gaia:version-start -->
117
- Current Gaia CLI version: `4.2.0`.
121
+ Current Gaia CLI version: `4.3.6`.
118
122
 
119
123
  ```bash
120
124
  curl -fsSL https://gaia.tiongson.co/install.sh | sh
@@ -130,17 +134,7 @@ npm install -g @gaia-registry/cli
130
134
  Requires Python 3.8+. The script prefers `pipx` if available, otherwise falls back to `pip install --user` and prints a PATH hint if needed.
131
135
 
132
136
  <details>
133
- <summary>pip / npm / pipx / Windows alternatives</summary>
134
-
135
- **pip (Python):**
136
- ```bash
137
- pip install gaia-cli
138
- ```
139
-
140
- **npm wrapper:**
141
- ```bash
142
- npm install -g @gaia-registry/cli
143
- ```
137
+ <summary>pipx / Windows alternatives</summary>
144
138
 
145
139
  **pipx:**
146
140
  ```bash
@@ -158,7 +152,7 @@ $env:PATH += ";" + (python -c "import sysconfig; print(sysconfig.get_path('scrip
158
152
  ```bash
159
153
  git clone https://github.com/mbtiongson1/gaia-skill-tree.git
160
154
  cd gaia-skill-tree
161
- pip install -e ".[embeddings,dev]"
155
+ pip install -e ".[embeddings,dev,docs]"
162
156
  ```
163
157
 
164
158
  The `dev` extra installs packaging/test tools such as `build` and `pytest`; without it,
@@ -377,9 +371,9 @@ Thank you to everyone who has expanded the Gaia registry.
377
371
  | [@rico-tiongson](https://github.com/rico-tiongson) | Collaborator: early feature contributions and ongoing pair programming |
378
372
  | [@Juno](https://github.com/Juno) | Key contributor: graph browser expansion, function-calling skill, RAG pipeline evidence, and CLI DX improvements |
379
373
 
380
- ### Named Skill Contributors
374
+ ### Named Skills
381
375
 
382
- | Contributor | Skills |
376
+ | Developers | Skills |
383
377
  |---|---|
384
378
  | [@ruvnet](https://github.com/ruvnet) | 48 — agentdb, flow-nexus, hive-mind-coordination, browser, and 44 others |
385
379
  | [@garrytan](https://github.com/garrytan) | 47 — gstack ecosystem: browse, qa, ship, review, benchmark, learn, and 41 others |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gaia-cli"
7
- version = "4.2.1"
7
+ version = "4.3.6"
8
8
  description = "Gaia AI Agent Skill Registry CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -561,6 +561,20 @@ def render_appraise_card(
561
561
  deriv_line = prefix + ", ".join(deriv_items)
562
562
  if len(derivatives) > 4:
563
563
  deriv_line += f" +{len(derivatives) - 4} more"
564
+ # Truncate at comma boundary instead of mid-word
565
+ if len(deriv_line) > inner:
566
+ truncated = prefix
567
+ for i, item in enumerate(deriv_items):
568
+ candidate = truncated + (", " if i > 0 else "") + item
569
+ if len(candidate) > inner - 2: # leave room for " …"
570
+ remaining = len(deriv_items) - i + (len(derivatives) - 4 if len(derivatives) > 4 else 0)
571
+ truncated += f" +{remaining} more" if remaining > 0 else ""
572
+ break
573
+ truncated = candidate
574
+ else:
575
+ if len(derivatives) > 4:
576
+ truncated += f" +{len(derivatives) - 4} more"
577
+ deriv_line = truncated
564
578
  lines.append(f"{bc}{V}{r} {fg(*COLOR_MUTED)}{_pad(deriv_line, inner)}{r} {bc}{V}{r}")
565
579
  else:
566
580
  lines.append(f"{bc}{V}{r} {fg(*COLOR_MUTED)}{_pad('Unlocks: (terminal skill)', inner)}{r} {bc}{V}{r}")
@@ -133,7 +133,9 @@ def collect_stats(registry_path: str | Path) -> dict:
133
133
  ]
134
134
 
135
135
  type_counts = Counter(skill.get("type", "unknown") for skill in skills)
136
- level_counts = Counter(skill.get("level", "?") for skill in skills)
136
+ level_counts = Counter(
137
+ skill["level"] for skill in skills if "level" in skill
138
+ )
137
139
  effective_level_counts = Counter()
138
140
  demerit_counts: Counter[str] = Counter()
139
141
  skills_with_demerits = 0
@@ -1205,7 +1205,7 @@ def graph_command(args: Any) -> None:
1205
1205
  pass # Degrade gracefully to canon mode
1206
1206
 
1207
1207
  out_path = write_graph_artifact(registry_path, output=output, fmt=fmt, user_ctx=user_ctx)
1208
- print(f" saved {os.path.basename(out_path)}")
1208
+ print(f" saved {out_path}")
1209
1209
 
1210
1210
  # Regenerate the GEXF from current node data
1211
1211
  if fmt == "html":
@@ -294,8 +294,8 @@ def init_command(args):
294
294
  config_dir = '.gaia'
295
295
  os.makedirs(config_dir, exist_ok=True)
296
296
  config_path = os.path.join(config_dir, 'config.toml')
297
- if os.path.exists(config_path):
298
- print("Gaia is already initialized in this repository.")
297
+ if os.path.exists(config_path) and not getattr(args, "force", False):
298
+ print("Gaia is already initialized in this repository. Use --force to overwrite.")
299
299
  return
300
300
 
301
301
  username = args.user or _detect_github_username()
@@ -472,16 +472,20 @@ def scan_command(args):
472
472
  skill_map = {s['id']: s for s in graph_data.get('skills', [])}
473
473
  unlocked = [s.get('skillId') for s in tree.get('unlockedSkills', [])]
474
474
  combos = get_combinations(graph_data, unlocked, resolved)
475
- if combos and not quiet:
476
- print("\nNew fusion candidates:")
477
- for c in combos:
478
- result_skill = skill_map.get(c['candidateResult'], {})
479
- result_type = result_skill.get('type', 'extra')
480
- print(render_fusion_diagram(
481
- c['detectedSkills'], c['candidateResult'], result_type,
482
- canon=canon, ctx=ctx
483
- ))
484
- print("Run `gaia fuse <skill>` to confirm.")
475
+ if combos:
476
+ # Persist fusion candidates so `gaia fuse` can find them
477
+ tree['pendingCombinations'] = combos
478
+ save_tree(username, tree, registry_path=args.registry)
479
+ if not quiet:
480
+ print("\nNew fusion candidates:")
481
+ for c in combos:
482
+ result_skill = skill_map.get(c['candidateResult'], {})
483
+ result_type = result_skill.get('type', 'extra')
484
+ print(render_fusion_diagram(
485
+ c['detectedSkills'], c['candidateResult'], result_type,
486
+ canon=canon, ctx=ctx
487
+ ))
488
+ print("Run `gaia fuse <skill>` to confirm.")
485
489
 
486
490
  # Path engine integration
487
491
  old_paths = load_paths()
@@ -537,7 +541,7 @@ def render_user_tree_outputs(username: str, tree: dict | None, graph_data: dict
537
541
  with open(html_path, "w", encoding="utf-8") as f:
538
542
  f.write(html)
539
543
  if not quiet:
540
- print(f" saved {os.path.basename(html_path)} & {os.path.basename(md_path)}")
544
+ print(f" saved {html_path} & {md_path}")
541
545
  return html_path, md_path
542
546
 
543
547
 
@@ -599,7 +603,8 @@ def lookup_command(args):
599
603
  display = skill.get("name") or f"/{skill_id}"
600
604
  print(f"{display}")
601
605
 
602
- print(f"Type: {skill.get('type', 'unknown')} Level: {skill.get('level', '?')}")
606
+ user_level = ctx.skill_level(skill_id) if ctx else skill.get('level', '?')
607
+ print(f"Type: {skill.get('type', 'unknown')} Level: {user_level}")
603
608
  if skill.get("description"):
604
609
  print(skill["description"])
605
610
 
@@ -792,7 +797,7 @@ def promote_command(args):
792
797
  return
793
798
  if not skill_id:
794
799
  # Try interactive picker
795
- candidates = promotable_candidates(username, args.registry)
800
+ candidates = promotable_candidates(args.registry, username)
796
801
  if candidates:
797
802
  picked = select_promotion_candidate(candidates, "Select skill to promote:")
798
803
  if picked:
@@ -1284,9 +1289,9 @@ def install_command(args):
1284
1289
  interactive_install(args.registry, location=location)
1285
1290
  return
1286
1291
  if not args.skill_id:
1287
- # Bare 'gaia install' -> update/sync all
1288
- update_skills(args.registry)
1289
- return
1292
+ print("Usage: gaia install <skill_id>", file=sys.stderr)
1293
+ print(" To update all installed skills, use: gaia update", file=sys.stderr)
1294
+ sys.exit(2)
1290
1295
 
1291
1296
  # Use suite logic if flagged or implicitly requested
1292
1297
  if getattr(args, 'ultimate', False) or getattr(args, 'suite', False):
@@ -1300,7 +1305,7 @@ def install_command(args):
1300
1305
 
1301
1306
  def uninstall_command(args):
1302
1307
  from gaia_cli.install import uninstall_skill
1303
- success = uninstall_skill(args.skill_id)
1308
+ success = uninstall_skill(args.skill_id.lstrip("/"))
1304
1309
  if not success:
1305
1310
  sys.exit(1)
1306
1311
 
@@ -1362,7 +1367,7 @@ def skills_command(args):
1362
1367
 
1363
1368
 
1364
1369
  available = [
1365
- {"id": sid, "name": meta.get("name") or sid, "level": meta.get("level", "?"), "description": meta.get("description", "")}
1370
+ {"id": sid, "name": meta.get("name") or sid, "level": meta.get("level", "?"), "type": meta.get("type", "basic"), "description": meta.get("description", "")}
1366
1371
  for sid, meta in list_available(args.registry)
1367
1372
  ]
1368
1373
  items = available + pending
@@ -1459,6 +1464,12 @@ def pull_command(args):
1459
1464
  print("Note: Registry could not be updated via git (no upstream configured). Local registry unchanged.", file=sys.stderr)
1460
1465
  else:
1461
1466
  print(f"Warning: git pull failed. Local registry unchanged.\n {stderr}", file=sys.stderr)
1467
+ else:
1468
+ stdout = res.stdout.strip()
1469
+ if "Already up to date" in stdout:
1470
+ print("Registry is already up to date.")
1471
+ else:
1472
+ print("Registry updated successfully.")
1462
1473
 
1463
1474
 
1464
1475
  def update_command(args):
@@ -1647,6 +1658,7 @@ def get_parser():
1647
1658
  init_parser.add_argument('--registry-ref', help='Gaia registry URL to write into .gaia/config.toml')
1648
1659
  init_parser.add_argument('--scan', action='append', help='Path to scan; repeat for multiple paths')
1649
1660
  init_parser.add_argument('--yes', action='store_true', help='Use non-interactive defaults')
1661
+ init_parser.add_argument('--force', action='store_true', help='Overwrite existing .gaia/config.toml')
1650
1662
  init_parser.add_argument(
1651
1663
  '--auto-prompt-combinations',
1652
1664
  action='store_true',
@@ -144,7 +144,12 @@ def render_unlock_path(
144
144
  total += c_total
145
145
  return owned, total
146
146
 
147
- owned_count, total_count = _count(tree)
147
+ # Count prerequisites only (children of root — root is the target, not a prereq).
148
+ owned_count, total_count = 0, 0
149
+ for child in tree.get('children', []):
150
+ c_owned, c_total = _count(child)
151
+ owned_count += c_owned
152
+ total_count += c_total
148
153
 
149
154
  # Render root line manually.
150
155
  root_sid = tree['id']
@@ -203,6 +203,11 @@ def open_intake_issue(username, batch_data, batch_path=None, repo_root="."):
203
203
 
204
204
  issue_url = issue.stdout.strip().splitlines()[-1] if issue.stdout.strip() else ""
205
205
  print(f"Success: intake issue opened ({issue_url}).")
206
+ # Clean up temp body file
207
+ try:
208
+ os.remove(body_path)
209
+ except OSError:
210
+ pass
206
211
  return issue_url or None
207
212
 
208
213
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gaia-cli
3
- Version: 4.2.1
3
+ Version: 4.3.6
4
4
  Summary: Gaia AI Agent Skill Registry CLI
5
5
  Author: Gaia contributors
6
6
  License: MIT
@@ -54,20 +54,18 @@ Dynamic: license-file
54
54
  </picture>
55
55
  </div>
56
56
 
57
- # Gaia - AI Agent Skill Registry
57
+ # Gaia - This is not a skill marketplace
58
58
 
59
- > The open, evidence-backed skill graph for AI agents: collect, evolve, and fuse capabilities into something legendary.
59
+ > This is an open, evidence-backed skill graph. The game is to name a skill to your repository--the best skill takes "origin".
60
60
  > Success means becoming the public record AI agent developers cite when making capability claims — the pkg.go.dev for agent skills.
61
61
 
62
- ### New here? Read [META.md](META.md) first
62
+ ### How does ranking work? Read [META.md](META.md) for a comprehensive list
63
63
 
64
64
  [![Validate](https://github.com/mbtiongson1/gaia-skill-tree/actions/workflows/validate.yml/badge.svg)](https://github.com/mbtiongson1/gaia-skill-tree/actions/workflows/validate.yml)
65
65
  [![License: MIT](https://img.shields.io/badge/License-MIT-c084fc.svg)](LICENSE)
66
66
  [![Website](https://img.shields.io/badge/Website-gaia.tiongson.co-f59e0b)](https://gaia.tiongson.co/)
67
67
 
68
- # NEW! Badges
69
-
70
- Have a named skill? Get yours now! Should look like this:
68
+ # Name a skill, get a badge.
71
69
 
72
70
  [![Gaia](https://gaia.tiongson.co/badges/_assets/mbtiongson1/gaia-curate.svg?repo=mbtiongson1%2Fgaia-skill-tree)](https://gaia.tiongson.co/u/mbtiongson1/)<br>
73
71
  [![Gaia rank](https://gaia.tiongson.co/badges/_assets/mbtiongson1/rank.svg?repo=mbtiongson1%2Fgaia-skill-tree)](https://gaia.tiongson.co/u/mbtiongson1/)<br>
@@ -81,9 +79,15 @@ Generate yours at **[gaia.tiongson.co/badges/](https://gaia.tiongson.co/badges/)
81
79
 
82
80
  ---
83
81
 
84
- ## The Registry
82
+ # Who maintains this?
83
+
84
+ Truth is, Gaia will exist even without anyone sending their skills.
85
+
86
+ I built this because skills should be attributed to the people who proved them. Permanently, not just until the repo goes private.
85
87
 
86
- Every AI agent capability exists somewhere on this graph. Skills start at the foundation tier, awaken through evidence, evolve through use, and fuse into things greater than the sum of their parts.
88
+ So that means, its the developers who make skills maintaining this. I have a thorough curation process, and the dev community is evidence on why this works. As long as developers making skills exists, this registry will exist. This is open-source, so feel free to contribute!
89
+
90
+ # The Skill Tree
87
91
 
88
92
  <!-- gaia:registry-start -->
89
93
  ```text
@@ -163,7 +167,7 @@ Skills rank up through **verifiable evidence** (Class A/B/C) and can be demoted
163
167
  **1. Install the CLI**
164
168
 
165
169
  <!-- gaia:version-start -->
166
- Current Gaia CLI version: `4.2.0`.
170
+ Current Gaia CLI version: `4.3.6`.
167
171
 
168
172
  ```bash
169
173
  curl -fsSL https://gaia.tiongson.co/install.sh | sh
@@ -179,17 +183,7 @@ npm install -g @gaia-registry/cli
179
183
  Requires Python 3.8+. The script prefers `pipx` if available, otherwise falls back to `pip install --user` and prints a PATH hint if needed.
180
184
 
181
185
  <details>
182
- <summary>pip / npm / pipx / Windows alternatives</summary>
183
-
184
- **pip (Python):**
185
- ```bash
186
- pip install gaia-cli
187
- ```
188
-
189
- **npm wrapper:**
190
- ```bash
191
- npm install -g @gaia-registry/cli
192
- ```
186
+ <summary>pipx / Windows alternatives</summary>
193
187
 
194
188
  **pipx:**
195
189
  ```bash
@@ -207,7 +201,7 @@ $env:PATH += ";" + (python -c "import sysconfig; print(sysconfig.get_path('scrip
207
201
  ```bash
208
202
  git clone https://github.com/mbtiongson1/gaia-skill-tree.git
209
203
  cd gaia-skill-tree
210
- pip install -e ".[embeddings,dev]"
204
+ pip install -e ".[embeddings,dev,docs]"
211
205
  ```
212
206
 
213
207
  The `dev` extra installs packaging/test tools such as `build` and `pytest`; without it,
@@ -426,9 +420,9 @@ Thank you to everyone who has expanded the Gaia registry.
426
420
  | [@rico-tiongson](https://github.com/rico-tiongson) | Collaborator: early feature contributions and ongoing pair programming |
427
421
  | [@Juno](https://github.com/Juno) | Key contributor: graph browser expansion, function-calling skill, RAG pipeline evidence, and CLI DX improvements |
428
422
 
429
- ### Named Skill Contributors
423
+ ### Named Skills
430
424
 
431
- | Contributor | Skills |
425
+ | Developers | Skills |
432
426
  |---|---|
433
427
  | [@ruvnet](https://github.com/ruvnet) | 48 — agentdb, flow-nexus, hive-mind-coordination, browser, and 44 others |
434
428
  | [@garrytan](https://github.com/garrytan) | 47 — gstack ecosystem: browse, qa, ship, review, benchmark, learn, and 41 others |
@@ -18,6 +18,7 @@ from gaia_cli.cardRenderer import (
18
18
  load_and_render,
19
19
  _pad,
20
20
  _wrap_lines,
21
+ render_appraise_card,
21
22
  )
22
23
 
23
24
 
@@ -520,3 +521,29 @@ class TestRenderFusionDiagram:
520
521
  # First line (shorter name) should be padded
521
522
  assert "/ab" in lines[0]
522
523
  assert "/longername" in lines[2]
524
+
525
+
526
+ def test_render_appraise_card_truncation():
527
+ skill_data = {
528
+ "id": "test-skill",
529
+ "name": "Test Skill",
530
+ "type": "basic",
531
+ "level": "0★",
532
+ "rarity": "common",
533
+ "description": "Short description.",
534
+ }
535
+ derivatives = [
536
+ {"id": "d1", "name": "First Derivative Skill Name"},
537
+ {"id": "d2", "name": "Second Derivative Skill Name"},
538
+ {"id": "d3", "name": "Third Derivative Skill Name"},
539
+ ]
540
+ output = render_appraise_card(
541
+ skill_data=skill_data,
542
+ prereq_status={},
543
+ derivatives=derivatives,
544
+ actions=[],
545
+ )
546
+ assert "First Derivative Skill Name" in output
547
+ assert "+2 more" in output
548
+ assert "Second Derivative" not in output
549
+
@@ -445,3 +445,25 @@ def test_gaia_uninstall_command_removes_skill(tmp_path, monkeypatch):
445
445
  from gaia_cli.install import load_manifest
446
446
  manifest = load_manifest()
447
447
  assert not any(e["id"] == "testuser/test-skill" for e in manifest["installed"])
448
+
449
+
450
+ def test_init_force_overwrite(tmp_path, monkeypatch, capsys):
451
+ monkeypatch.chdir(tmp_path)
452
+
453
+ # First init
454
+ run_cli(monkeypatch, ["init", "--user", "firstuser", "--yes"])
455
+ config = parse_config(tmp_path / ".gaia" / "config.toml")
456
+ assert config["username"] == "firstuser"
457
+
458
+ # Second init without --force (should print message and not overwrite)
459
+ run_cli(monkeypatch, ["init", "--user", "seconduser", "--yes"])
460
+ output = capsys.readouterr().out
461
+ assert "Gaia is already initialized in this repository. Use --force to overwrite." in output
462
+ config = parse_config(tmp_path / ".gaia" / "config.toml")
463
+ assert config["username"] == "firstuser" # unchanged
464
+
465
+ # Third init with --force (should overwrite)
466
+ run_cli(monkeypatch, ["init", "--user", "seconduser", "--yes", "--force"])
467
+ config = parse_config(tmp_path / ".gaia" / "config.toml")
468
+ assert config["username"] == "seconduser" # overwritten
469
+
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import os
3
3
  import subprocess
4
+ import sys
4
5
  import tempfile
5
6
  import unittest
6
7
 
@@ -15,7 +16,7 @@ def run_validate_intake(intake_dir, *extra_args):
15
16
  env["PYTHONIOENCODING"] = "utf-8"
16
17
  result = subprocess.run(
17
18
  [
18
- "python3",
19
+ sys.executable,
19
20
  VALIDATE_INTAKE_SCRIPT,
20
21
  "--intake-dir",
21
22
  intake_dir,
@@ -236,23 +236,23 @@ class TestRenderUnlockPath:
236
236
  def test_basic_leaf_renders(self, linear_graph):
237
237
  text = render_unlock_path(linear_graph, "a", set())
238
238
  assert "a" in text
239
- # leaf has no children, summary should say 0 owned out of 1
240
- assert "0 / 1" in text
239
+ # leaf has no children, summary should say 0 owned out of 0
240
+ assert "0 / 0" in text
241
241
 
242
242
  def test_footer_counts_correct(self, linear_graph):
243
243
  text = render_unlock_path(linear_graph, "c", set())
244
- # 3 nodes total (a, b, c), 0 owned
245
- assert "0 / 3" in text
246
- assert "3 skill(s) needed" in text
244
+ # 2 prerequisites total (a, b), 0 owned
245
+ assert "0 / 2" in text
246
+ assert "2 skill(s) needed" in text
247
247
 
248
248
  def test_footer_with_owned(self, linear_graph):
249
249
  # unlock_path stops recursing into owned nodes, so the visible tree
250
250
  # for 'c' with owned={'a','b'} is: c(missing) + b(owned, no children).
251
251
  # 'a' is not in the tree because b is already owned → recursion stops.
252
- # Count: 2 nodes total, 1 owned (b), 1 missing (c).
252
+ # Count: 1 prerequisite total (b), 1 owned (b).
253
253
  text = render_unlock_path(linear_graph, "c", {"a", "b"})
254
- assert "1 / 2" in text
255
- assert "1 skill(s) needed" in text
254
+ assert "1 / 1" in text
255
+ assert "0 skill(s) needed" in text
256
256
 
257
257
  def test_owned_only_prunes_owned_branches(self, linear_graph):
258
258
  """--owned-only prunes the display of owned 'b' from the output."""
@@ -37,7 +37,7 @@ class TestGaiaPush(unittest.TestCase):
37
37
  env["PYTHONIOENCODING"] = "utf-8"
38
38
  result = subprocess.run(
39
39
  [
40
- "python3",
40
+ sys.executable,
41
41
  CLI_PATH,
42
42
  "--registry",
43
43
  REPO_ROOT,
@@ -83,7 +83,7 @@ class TestGaiaPush(unittest.TestCase):
83
83
  env["PYTHONIOENCODING"] = "utf-8"
84
84
  result = subprocess.run(
85
85
  [
86
- "python3",
86
+ sys.executable,
87
87
  CLI_PATH,
88
88
  "--registry",
89
89
  registry,
@@ -114,3 +114,23 @@ def test_stats_cli_prints_summary(tmp_path, monkeypatch, capsys):
114
114
  assert "Gaia Registry — 4 skills 1 edges" in output
115
115
  assert "Class A" in output
116
116
  assert "Effective level breakdown" in output
117
+
118
+
119
+ def test_collect_stats_missing_level(tmp_path):
120
+ registry = tmp_path / "registry"
121
+ registry.mkdir(parents=True, exist_ok=True)
122
+ (registry / "gaia.json").write_text(
123
+ json.dumps(
124
+ {
125
+ "skills": [
126
+ {"id": "tokenize", "type": "basic", "evidence": []}, # No 'level' key
127
+ ],
128
+ "edges": [],
129
+ }
130
+ ),
131
+ encoding="utf-8",
132
+ )
133
+ stats = collect_stats(tmp_path)
134
+ assert "?" not in stats["level_counts"]
135
+ assert "level_counts" in stats
136
+
@@ -17,7 +17,7 @@ def run_validate(graph_path):
17
17
  env = os.environ.copy()
18
18
  env["PYTHONIOENCODING"] = "utf-8"
19
19
  result = subprocess.run(
20
- ["python3", VALIDATE_SCRIPT, "--graph", graph_path],
20
+ [sys.executable, VALIDATE_SCRIPT, "--graph", graph_path],
21
21
  capture_output=True,
22
22
  text=True,
23
23
  encoding="utf-8",
@@ -210,6 +210,46 @@ class TestNamedSkillValidation(unittest.TestCase):
210
210
  f"Expected unresolved-ref error, got: {errors}",
211
211
  )
212
212
 
213
+ def test_invalid_github_url_casing_fails_validation(self):
214
+ """validate_named_skills reports an error when links.github URL has invalid casing (e.g. skill.md)."""
215
+ import tempfile
216
+ import shutil
217
+ from scripts.validate import validate_named_skills
218
+
219
+ temp_named_dir = tempfile.mkdtemp()
220
+ try:
221
+ fake_author_dir = os.path.join(temp_named_dir, "fake_author")
222
+ os.makedirs(fake_author_dir)
223
+
224
+ fake_skill_file = os.path.join(fake_author_dir, "skill_with_bad_casing.md")
225
+ frontmatter = (
226
+ "---\n"
227
+ "id: fake_author/skill_with_bad_casing\n"
228
+ "name: Bad Casing Skill\n"
229
+ "contributor: fake_author\n"
230
+ "origin: true\n"
231
+ "genericSkillRef: web-search\n"
232
+ "status: named\n"
233
+ "level: 2★\n"
234
+ "description: A skill that references lowercase skill.md in links.github.\n"
235
+ "links:\n"
236
+ " github: https://github.com/fake_author/skills/blob/main/skills/skill.md\n"
237
+ "createdAt: '2026-06-07'\n"
238
+ "updatedAt: '2026-06-07'\n"
239
+ "---\n"
240
+ )
241
+ with open(fake_skill_file, "w", encoding="utf-8") as f:
242
+ f.write(frontmatter)
243
+
244
+ graph = {"skills": [{"id": "web-search"}]}
245
+ errors = validate_named_skills(graph, named_dir=temp_named_dir)
246
+ self.assertTrue(
247
+ any("invalid casing" in e and "SKILL.md" in e for e in errors),
248
+ f"Expected casing error, got: {errors}"
249
+ )
250
+ finally:
251
+ shutil.rmtree(temp_named_dir)
252
+
213
253
 
214
254
  if __name__ == "__main__":
215
255
  unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes