@rayul/kordis 0.1.3 → 0.1.5
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.
- package/assets/KORDIS.md +5 -4
- package/assets/kordis-search/SKILL.md +36 -8
- package/assets/kordis-social/SKILL.md +82 -21
- package/assets/kordis-using/SKILL.md +3 -3
- package/dist/index.js +185 -17
- package/package.json +1 -1
package/assets/KORDIS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: kordis
|
|
3
3
|
description: Use Kordis whenever the user mentions finding, installing, sharing, or publishing skills, project-rules, custom-agents, MCP servers, or hooks; or names any `<username>/<slug>` identifier. Pushy on purpose — Claude under-triggers. Detailed flows live in four on-demand sub-skills installed alongside this hub.
|
|
4
4
|
type: skill
|
|
5
|
-
version: 0.1.
|
|
5
|
+
version: 0.1.5
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Kordis
|
|
@@ -18,14 +18,15 @@ Trigger Kordis when the user:
|
|
|
18
18
|
- names a `<username>/<slug>` identifier
|
|
19
19
|
- asks what is trending or rising
|
|
20
20
|
|
|
21
|
-
Verbs: `kordis search`, `info`, `read`, `pull`, `push`, `
|
|
22
|
-
ALWAYS pass `--json` when parsing
|
|
21
|
+
Verbs: `kordis search`, `info`, `read`, `pull`, `push`, `comment`, `star`,
|
|
22
|
+
`unstar`, `whoami`/`login`/`logout`. ALWAYS pass `--json` when parsing
|
|
23
|
+
programmatically.
|
|
23
24
|
|
|
24
25
|
Detail lives in four on-demand sub-skills (auto-loaded by description match):
|
|
25
26
|
- `kordis-search` — find and browse packages
|
|
26
27
|
- `kordis-using` — `read` vs `pull`, behaviour per package type, attribution
|
|
27
28
|
- `kordis-publishing` — author and push packages
|
|
28
|
-
- `kordis-social` — identity
|
|
29
|
+
- `kordis-social` — identity, session, comments, and stars
|
|
29
30
|
|
|
30
31
|
If `kordis: command not found`, install with `npm i -g @rayul/kordis` and
|
|
31
32
|
ensure your npm-global `bin` (commonly `~/.npm-global/bin`) is on `PATH`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kordis-search
|
|
3
|
-
description: Use whenever the user wants to find, browse, or discover Kordis packages. Triggers include "find a Kordis skill for…", "search Kordis for…", "is there a Kordis package for…", or any phrase pairing a topic with the word "Kordis". Pushy on purpose — Claude tends to skip Kordis search when it would help.
|
|
3
|
+
description: Use whenever the user wants to find, browse, or discover Kordis packages. Triggers include "find a Kordis skill for…", "search Kordis for…", "what's trending on Kordis", "what's rising on Kordis", "is there a Kordis package for…", or any phrase pairing a topic with the word "Kordis". Pushy on purpose — Claude tends to skip Kordis search when it would help.
|
|
4
4
|
type: skill
|
|
5
5
|
allowed-tools: ["Bash(kordis:*)"]
|
|
6
6
|
---
|
|
@@ -16,11 +16,16 @@ search results — NEVER fabricate slugs.
|
|
|
16
16
|
### `kordis search [query...] [options]`
|
|
17
17
|
Keyword search; `--json` for parsing.
|
|
18
18
|
|
|
19
|
-
| flag
|
|
20
|
-
|
|
|
21
|
-
| `--type <t>`
|
|
22
|
-
| `--tool <s>`
|
|
23
|
-
| `--
|
|
19
|
+
| flag | meaning |
|
|
20
|
+
| ---------------- | ------------------------------------------------------------------------ |
|
|
21
|
+
| `--type <t>` | `skill`, `mcp-server`, `project-rules`, `custom-agent`, `hook` |
|
|
22
|
+
| `--tool <s>` | filter by compatible tool (`claude-code`, `codex`, `cursor`, …) |
|
|
23
|
+
| `--tier <t>` | filter by portability tier `A`/`B`/`C`/`D` |
|
|
24
|
+
| `--sort <m>` | `relevance` (default), `stars`, `downloads`, `recent`, `updated` |
|
|
25
|
+
| `--trending` | list packages trending in `--window` (overrides `--sort`) |
|
|
26
|
+
| `--rising` | list rising packages by 7d acceleration (overrides `--sort`) |
|
|
27
|
+
| `--window <w>` | `24h` (default), `7d`, or `30d` — only honoured with `--trending` |
|
|
28
|
+
| `--limit <n>` | max results (default 20) |
|
|
24
29
|
|
|
25
30
|
### `kordis info <full_slug> --json`
|
|
26
31
|
Inspect metadata (title, description, type, tier, version, author, stars,
|
|
@@ -30,8 +35,11 @@ review status, dependencies) before reading or pulling.
|
|
|
30
35
|
|
|
31
36
|
### 1. Form the query
|
|
32
37
|
Pick a keyword that matches the user's task; restrict by `--type` if the user
|
|
33
|
-
named a package type, and by `--tool` if the user named their tool.
|
|
34
|
-
|
|
38
|
+
named a package type, and by `--tool` if the user named their tool. For
|
|
39
|
+
"what's trending / rising" intents skip the keyword — pass `--trending` or
|
|
40
|
+
`--rising` instead.
|
|
41
|
+
**Success criteria**: a non-empty query OR a discovery flag, plus (when known)
|
|
42
|
+
the right filters.
|
|
35
43
|
|
|
36
44
|
### 2. Run the search
|
|
37
45
|
ALWAYS with `--json`. **Success criteria**: CLI exits 0 and returns a results
|
|
@@ -39,6 +47,8 @@ array.
|
|
|
39
47
|
|
|
40
48
|
### 3. Triage the results
|
|
41
49
|
- Prefer `review_status: passed`, higher `stars`, then `tier: A`.
|
|
50
|
+
- For trending results, the `trending_score` field is populated — surface it
|
|
51
|
+
when comparing.
|
|
42
52
|
- IMPORTANT: if results are 0, RELAX one filter at a time before giving up.
|
|
43
53
|
Do NOT invent a slug to fill the gap.
|
|
44
54
|
- Surface the top 3–5 with slug, type, tier, stars, one-line description.
|
|
@@ -67,3 +77,21 @@ User: "any Cursor-compatible package for code review?"
|
|
|
67
77
|
- kordis search "code review" --tool cursor --json
|
|
68
78
|
- present top results scoped to Cursor compatibility
|
|
69
79
|
</example>
|
|
80
|
+
|
|
81
|
+
<example>
|
|
82
|
+
User: "what's trending on Kordis this week?"
|
|
83
|
+
- kordis search --trending --window 7d --json
|
|
84
|
+
- show top 5–10 with their `trending_score`; do NOT fetch bodies unless asked
|
|
85
|
+
</example>
|
|
86
|
+
|
|
87
|
+
<example>
|
|
88
|
+
User: "what's rising on Kordis?"
|
|
89
|
+
- kordis search --rising --json
|
|
90
|
+
- present accelerating packages over the last 7 days
|
|
91
|
+
</example>
|
|
92
|
+
|
|
93
|
+
<example>
|
|
94
|
+
User: "show me the most-downloaded skills"
|
|
95
|
+
- kordis search --type skill --sort downloads --json
|
|
96
|
+
- list top results
|
|
97
|
+
</example>
|
|
@@ -1,59 +1,120 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kordis-social
|
|
3
|
-
description: Use whenever the user wants to log into Kordis, log out,
|
|
3
|
+
description: Use whenever the user wants to log into Kordis, log out, check identity, post a typed comment on a Kordis package, or star/unstar a package. Triggers include "log into Kordis", "kordis login", "who am I logged in as on Kordis", "log me out of Kordis", "leave a tip on <slug>", "report a bug on <slug>", "comment on <slug>", "star <slug>", "unstar <slug>", "favourite <slug>".
|
|
4
4
|
type: skill
|
|
5
5
|
allowed-tools: ["Bash(kordis:*)"]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Kordis: Identity &
|
|
8
|
+
# Kordis: Identity, Comments, & Stars
|
|
9
9
|
|
|
10
10
|
## Goal
|
|
11
|
-
Drive login state
|
|
11
|
+
Drive the user's login state and the social actions Kordis exposes — typed
|
|
12
|
+
comments and stars.
|
|
12
13
|
|
|
13
|
-
##
|
|
14
|
+
## Identity commands
|
|
14
15
|
|
|
15
16
|
### `kordis whoami [--json]`
|
|
16
|
-
Show the currently authenticated user (or
|
|
17
|
+
Show the currently authenticated user (or anonymous state).
|
|
17
18
|
|
|
18
19
|
### `kordis login [--provider <name>]`
|
|
19
20
|
Opens browser device-flow pairing. `--provider` defaults to `discord`.
|
|
20
|
-
Required before
|
|
21
|
+
Required before `push`, `comment`, `star`, or `unstar`.
|
|
21
22
|
|
|
22
23
|
### `kordis logout`
|
|
23
24
|
Clears local tokens.
|
|
24
25
|
|
|
26
|
+
## Comment command
|
|
27
|
+
|
|
28
|
+
### `kordis comment <full_slug> --body <text> [--kind <kind>] [--title <text>] [--json]`
|
|
29
|
+
Post a top-level comment on a package. Auth required.
|
|
30
|
+
|
|
31
|
+
| flag | meaning |
|
|
32
|
+
| -------------- | ---------------------------------------------------------------- |
|
|
33
|
+
| `--body <t>` | required, 1–10000 chars |
|
|
34
|
+
| `--kind <k>` | `comment` (default), `tip`, `report`, `praise`, `question` |
|
|
35
|
+
| `--title <t>` | 1–140 chars; honoured for top-level posts only |
|
|
36
|
+
|
|
37
|
+
Replies, edits, status flips (open/resolved on a `report`), and listing
|
|
38
|
+
existing comments are NOT yet exposed in the CLI. Direct the user to
|
|
39
|
+
`https://kordis.store/p/<full_slug>` for those interactions until verbs land.
|
|
40
|
+
|
|
41
|
+
## Star commands
|
|
42
|
+
|
|
43
|
+
### `kordis star <full_slug> [--json]`
|
|
44
|
+
Mark a package as a favourite. Idempotent — re-running on an already-starred
|
|
45
|
+
package returns the current count without a duplicate. Auth required.
|
|
46
|
+
|
|
47
|
+
### `kordis unstar <full_slug> [--json]`
|
|
48
|
+
Remove your star. Idempotent — silent no-op when not previously starred.
|
|
49
|
+
Auth required.
|
|
50
|
+
|
|
51
|
+
Stars feed `--sort stars` ordering on `kordis search` and contribute to the
|
|
52
|
+
`trending_score`.
|
|
53
|
+
|
|
25
54
|
## Steps
|
|
26
55
|
|
|
27
56
|
### 1. Inspect identity (when in doubt)
|
|
28
57
|
`kordis whoami --json`. **Success criteria**: returns either a username +
|
|
29
|
-
profile, or the anonymous-state error indicating
|
|
58
|
+
profile, or the anonymous-state error indicating not logged in.
|
|
59
|
+
|
|
60
|
+
### 2. Match command to user intent
|
|
61
|
+
- "log me into Kordis" → `kordis login`. Tell the user a browser device-flow
|
|
62
|
+
page will open; they must approve on their auth provider.
|
|
63
|
+
- "log me out" → `kordis logout`.
|
|
64
|
+
- "leave a tip / question / praise / bug-report / comment on <slug>" → pick
|
|
65
|
+
the matching `--kind`, generate a concise `--title` if it's a top-level
|
|
66
|
+
post, and put the substantive content in `--body`.
|
|
67
|
+
- "star / favourite / bookmark <slug>" → `kordis star <full_slug>`.
|
|
68
|
+
- "unstar / unfavourite <slug>" → `kordis unstar <full_slug>`.
|
|
30
69
|
|
|
31
|
-
###
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`kordis whoami --json` returns a username.
|
|
35
|
-
- "log me out" → `kordis logout`. **Success criteria**: subsequent
|
|
36
|
-
`kordis whoami --json` is anonymous.
|
|
70
|
+
### 3. Authenticate before posting
|
|
71
|
+
If a command returns `not_authenticated` (exit 10), run `kordis login` and
|
|
72
|
+
retry. **Success criteria**: command exits 0; surface returned IDs / counts.
|
|
37
73
|
|
|
38
74
|
## Examples
|
|
39
75
|
|
|
40
76
|
<example>
|
|
41
77
|
User: "who am I logged into Kordis as?"
|
|
42
78
|
- kordis whoami --json
|
|
43
|
-
- show username + display_name
|
|
79
|
+
- show username + display_name
|
|
44
80
|
</example>
|
|
45
81
|
|
|
46
82
|
<example>
|
|
47
83
|
User: "log into Kordis"
|
|
48
84
|
- kordis login
|
|
49
|
-
- explain that a browser device-flow page will open
|
|
50
|
-
|
|
51
|
-
|
|
85
|
+
- explain that a browser device-flow page will open
|
|
86
|
+
- after they confirm, run `kordis whoami --json` to verify
|
|
87
|
+
</example>
|
|
88
|
+
|
|
89
|
+
<example>
|
|
90
|
+
User: "leave a tip on foo/bar saying it pairs well with baz/qux"
|
|
91
|
+
- kordis comment foo/bar --kind tip --title "Pairs well with baz/qux" \
|
|
92
|
+
--body "Combine baz/qux's <feature> with this skill's <step> to <outcome>." --json
|
|
93
|
+
- show returned `{id, kind, title}` so the user can find their post on the web UI
|
|
94
|
+
</example>
|
|
95
|
+
|
|
96
|
+
<example>
|
|
97
|
+
User: "report that the v0.3.0 release of foo/bar is broken on macOS"
|
|
98
|
+
- kordis comment foo/bar --kind report --title "v0.3.0 broken on macOS" \
|
|
99
|
+
--body "<reproducible details>" --json
|
|
100
|
+
- mention that opening/resolving the report later requires the web UI
|
|
101
|
+
</example>
|
|
102
|
+
|
|
103
|
+
<example>
|
|
104
|
+
User: "star foo/bar"
|
|
105
|
+
- kordis star foo/bar --json
|
|
106
|
+
- show new star count
|
|
107
|
+
</example>
|
|
108
|
+
|
|
109
|
+
<example>
|
|
110
|
+
User: "unstar foo/bar"
|
|
111
|
+
- kordis unstar foo/bar --json
|
|
112
|
+
- show updated count
|
|
52
113
|
</example>
|
|
53
114
|
|
|
54
115
|
## Limitations
|
|
55
116
|
|
|
56
|
-
The CLI does NOT yet expose
|
|
57
|
-
|
|
58
|
-
truthfully that
|
|
59
|
-
|
|
117
|
+
The CLI does NOT yet expose follow, listing comments, replies, editing or
|
|
118
|
+
moderating comments, or notifications. If the user asks for any of those, tell
|
|
119
|
+
them truthfully that the CLI verb is not implemented yet — do NOT fabricate a
|
|
120
|
+
command. For now direct them to `https://kordis.store`.
|
|
@@ -30,9 +30,9 @@ DEFAULT to `read` when you spontaneously want to consult a skill. DEFAULT to
|
|
|
30
30
|
|
|
31
31
|
## Commands
|
|
32
32
|
|
|
33
|
-
### `kordis read <full_slug>[@<version>] [--allow-pending] [--
|
|
33
|
+
### `kordis read <full_slug>[@<version>] [--allow-pending] [--pin <semver>] [--json]`
|
|
34
34
|
Returns the full body (Markdown) of a text-bearing package, plus an
|
|
35
|
-
`attribution` string. `--
|
|
35
|
+
`attribution` string. `--pin <semver>` overrides any `@suffix` on the slug.
|
|
36
36
|
|
|
37
37
|
### `kordis pull <full_slug>[@<version>] [options]`
|
|
38
38
|
Writes files into the current project.
|
|
@@ -116,7 +116,7 @@ User: "install the github MCP server from Kordis"
|
|
|
116
116
|
|
|
117
117
|
<example>
|
|
118
118
|
User: "use the v0.2.0 of <full_slug> specifically"
|
|
119
|
-
- kordis read <full_slug> --
|
|
119
|
+
- kordis read <full_slug> --pin 0.2.0 --json
|
|
120
120
|
(or: kordis read <full_slug>@0.2.0 --json)
|
|
121
121
|
</example>
|
|
122
122
|
|
package/dist/index.js
CHANGED
|
@@ -459,7 +459,7 @@ var init_auth = __esm({
|
|
|
459
459
|
|
|
460
460
|
// ../../packages/contracts/src/api.ts
|
|
461
461
|
import { z as z9 } from "zod";
|
|
462
|
-
var SearchQuerySchema, SearchResponseSchema, TrendingQuerySchema, RisingQuerySchema, PublishPackageRequestSchema, PublishWaitQuerySchema, PublishPackageResponseSchema, PackagePathParamsSchema, ContentQuerySchema, PackageContentResponseSchema, JitReadRequestSchema, JitReadResponseSchema, PullPackageResponseSchema, ListVersionsResponseSchema, VersionDiffQuerySchema, ListCommentsQuerySchema, ListCommentsResponseSchema, UserProfileResponseSchema, UserPackagesQuerySchema;
|
|
462
|
+
var SearchQuerySchema, SearchResponseSchema, TrendingQuerySchema, RisingQuerySchema, StarResponseSchema, PublishPackageRequestSchema, PublishWaitQuerySchema, PublishPackageResponseSchema, PackagePathParamsSchema, ContentQuerySchema, PackageContentResponseSchema, JitReadRequestSchema, JitReadResponseSchema, PullPackageResponseSchema, ListVersionsResponseSchema, VersionDiffQuerySchema, ListCommentsQuerySchema, ListCommentsResponseSchema, UserProfileResponseSchema, UserPackagesQuerySchema;
|
|
463
463
|
var init_api = __esm({
|
|
464
464
|
"../../packages/contracts/src/api.ts"() {
|
|
465
465
|
"use strict";
|
|
@@ -493,6 +493,11 @@ var init_api = __esm({
|
|
|
493
493
|
type: HarnessTypeSchema.optional(),
|
|
494
494
|
limit: z9.coerce.number().int().min(1).max(100).default(20)
|
|
495
495
|
});
|
|
496
|
+
StarResponseSchema = z9.object({
|
|
497
|
+
full_slug: FullSlugSchema,
|
|
498
|
+
starred: z9.boolean(),
|
|
499
|
+
star_count: z9.number().int().nonnegative()
|
|
500
|
+
});
|
|
496
501
|
PublishPackageRequestSchema = z9.object({
|
|
497
502
|
/**
|
|
498
503
|
* Raw source content — YAML frontmatter + markdown body. Server parses and
|
|
@@ -857,12 +862,36 @@ var init_client = __esm({
|
|
|
857
862
|
recent() {
|
|
858
863
|
return this.request("/api/packages/recent");
|
|
859
864
|
}
|
|
860
|
-
trending(
|
|
861
|
-
return this.request("/api/packages/trending", {
|
|
865
|
+
trending(opts = {}) {
|
|
866
|
+
return this.request("/api/packages/trending", {
|
|
867
|
+
query: {
|
|
868
|
+
window: opts.window ?? "24h",
|
|
869
|
+
...opts.type ? { type: opts.type } : {},
|
|
870
|
+
...opts.limit ? { limit: opts.limit } : {}
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
rising(opts = {}) {
|
|
875
|
+
return this.request("/api/packages/rising", {
|
|
876
|
+
query: {
|
|
877
|
+
...opts.type ? { type: opts.type } : {},
|
|
878
|
+
...opts.limit ? { limit: opts.limit } : {}
|
|
879
|
+
}
|
|
880
|
+
});
|
|
862
881
|
}
|
|
863
882
|
popular() {
|
|
864
883
|
return this.request("/api/packages/popular");
|
|
865
884
|
}
|
|
885
|
+
star(username, slug) {
|
|
886
|
+
return this.request(`/api/packages/${username}/${slug}/star`, {
|
|
887
|
+
method: "POST"
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
unstar(username, slug) {
|
|
891
|
+
return this.request(`/api/packages/${username}/${slug}/star`, {
|
|
892
|
+
method: "DELETE"
|
|
893
|
+
});
|
|
894
|
+
}
|
|
866
895
|
versions(username, slug) {
|
|
867
896
|
return this.request(
|
|
868
897
|
`/api/packages/${username}/${slug}/versions`
|
|
@@ -932,7 +961,7 @@ var init_src2 = __esm({
|
|
|
932
961
|
|
|
933
962
|
// src/index.ts
|
|
934
963
|
init_src2();
|
|
935
|
-
import { Command as
|
|
964
|
+
import { Command as Command12 } from "commander";
|
|
936
965
|
|
|
937
966
|
// src/commands/login.ts
|
|
938
967
|
import { Command } from "commander";
|
|
@@ -1205,15 +1234,47 @@ function whoamiCommand() {
|
|
|
1205
1234
|
|
|
1206
1235
|
// src/commands/search.ts
|
|
1207
1236
|
import { Command as Command3 } from "commander";
|
|
1237
|
+
var SORT_MODES = [
|
|
1238
|
+
"relevance",
|
|
1239
|
+
"stars",
|
|
1240
|
+
"downloads",
|
|
1241
|
+
"recent",
|
|
1242
|
+
"updated",
|
|
1243
|
+
"trending",
|
|
1244
|
+
"rising"
|
|
1245
|
+
];
|
|
1246
|
+
var TIME_WINDOWS = ["24h", "7d", "30d"];
|
|
1208
1247
|
function searchCommand() {
|
|
1209
|
-
return new Command3("search").description("search the Kordis registry").argument("[query...]", "keywords to match against title/description").option("--type <type>", "filter by harness type (skill|mcp-server|project-rules|custom-agent|hook)").option("--tool <tool>", "filter by compatible tool (claude-code|codex|cursor|...)").option("--limit <n>", "max results", (v) => parseInt(v, 10), 20).action(async (query, opts) => {
|
|
1248
|
+
return new Command3("search").description("search the Kordis registry").argument("[query...]", "keywords to match against title/description").option("--type <type>", "filter by harness type (skill|mcp-server|project-rules|custom-agent|hook)").option("--tool <tool>", "filter by compatible tool (claude-code|codex|cursor|...)").option("--tier <tier>", "filter by portability tier (A|B|C|D)").option("--sort <mode>", `sort: ${SORT_MODES.join("|")}`).option("--trending", "list trending packages (overrides --sort)", false).option("--rising", "list rising packages by 7d acceleration (overrides --sort)", false).option("--window <w>", `time window for --trending: ${TIME_WINDOWS.join("|")}`, "24h").option("--limit <n>", "max results", (v) => parseInt(v, 10), 20).action(async (query, opts) => {
|
|
1249
|
+
if (opts.sort && !SORT_MODES.includes(opts.sort)) {
|
|
1250
|
+
throw new Error(`--sort must be one of ${SORT_MODES.join(", ")}`);
|
|
1251
|
+
}
|
|
1252
|
+
if (opts.window && !TIME_WINDOWS.includes(opts.window)) {
|
|
1253
|
+
throw new Error(`--window must be one of ${TIME_WINDOWS.join(", ")}`);
|
|
1254
|
+
}
|
|
1210
1255
|
const bundle = await useClient();
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1256
|
+
let res;
|
|
1257
|
+
if (opts.rising) {
|
|
1258
|
+
res = await bundle.api.rising({
|
|
1259
|
+
...opts.type ? { type: opts.type } : {},
|
|
1260
|
+
limit: opts.limit
|
|
1261
|
+
});
|
|
1262
|
+
} else if (opts.trending) {
|
|
1263
|
+
res = await bundle.api.trending({
|
|
1264
|
+
window: opts.window ?? "24h",
|
|
1265
|
+
...opts.type ? { type: opts.type } : {},
|
|
1266
|
+
limit: opts.limit
|
|
1267
|
+
});
|
|
1268
|
+
} else {
|
|
1269
|
+
res = await bundle.api.search({
|
|
1270
|
+
q: query.join(" ") || void 0,
|
|
1271
|
+
type: opts.type ? [opts.type] : void 0,
|
|
1272
|
+
tool: opts.tool ? [opts.tool] : void 0,
|
|
1273
|
+
tier: opts.tier,
|
|
1274
|
+
sort: opts.sort ?? "relevance",
|
|
1275
|
+
limit: opts.limit
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1217
1278
|
printDual({
|
|
1218
1279
|
json: res,
|
|
1219
1280
|
human: () => {
|
|
@@ -1226,11 +1287,20 @@ function searchCommand() {
|
|
|
1226
1287
|
`${c.bold(p.full_slug)} ${c.gray(`v${p.current_version}`)} ${c.cyan(`[${p.type}]`)}`
|
|
1227
1288
|
);
|
|
1228
1289
|
printHuman(` ${p.description}`);
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1290
|
+
const trail = [
|
|
1291
|
+
`\u2605 ${p.stars}`,
|
|
1292
|
+
`\u21E3 ${p.downloads}`,
|
|
1293
|
+
`${p.author.username}${p.author.is_verified ? " \u2713" : ""}`
|
|
1294
|
+
];
|
|
1295
|
+
if (typeof p.trending_score === "number") {
|
|
1296
|
+
trail.push(`score ${p.trending_score.toFixed(2)}`);
|
|
1297
|
+
}
|
|
1298
|
+
printHuman(c.gray(` ${trail.join(" ")}`));
|
|
1232
1299
|
printHuman("");
|
|
1233
1300
|
}
|
|
1301
|
+
if (res.next_cursor) {
|
|
1302
|
+
printHuman(c.gray(`(more available \u2014 pass --cursor ${res.next_cursor})`));
|
|
1303
|
+
}
|
|
1234
1304
|
}
|
|
1235
1305
|
});
|
|
1236
1306
|
});
|
|
@@ -2229,12 +2299,12 @@ async function detectTool(root) {
|
|
|
2229
2299
|
// src/commands/read.ts
|
|
2230
2300
|
import { Command as Command6 } from "commander";
|
|
2231
2301
|
function readCommand() {
|
|
2232
|
-
return new Command6("read").description("fetch a package body into the agent context (no install)").argument("<full_slug>", "package identifier {username}/{slug} or {username}/{slug}@{version}").option("--allow-pending", "allow versions whose AI review has not passed", false).option("--
|
|
2302
|
+
return new Command6("read").description("fetch a package body into the agent context (no install)").argument("<full_slug>", "package identifier {username}/{slug} or {username}/{slug}@{version}").option("--allow-pending", "allow versions whose AI review has not passed", false).option("--pin <semver>", "pin to an exact version (overrides @suffix)").action(
|
|
2233
2303
|
async (rawSlug, opts) => {
|
|
2234
2304
|
const atIdx = rawSlug.lastIndexOf("@");
|
|
2235
2305
|
const fullSlug = atIdx > 0 ? rawSlug.slice(0, atIdx) : rawSlug;
|
|
2236
2306
|
const inlineVersion = atIdx > 0 ? rawSlug.slice(atIdx + 1) : void 0;
|
|
2237
|
-
const version = opts.
|
|
2307
|
+
const version = opts.pin ?? inlineVersion;
|
|
2238
2308
|
const [username, slug] = fullSlug.split("/");
|
|
2239
2309
|
if (!username || !slug) {
|
|
2240
2310
|
throw new Error('full_slug must be "{username}/{slug}" (optional "@version")');
|
|
@@ -2509,9 +2579,104 @@ function setupCommand() {
|
|
|
2509
2579
|
});
|
|
2510
2580
|
}
|
|
2511
2581
|
|
|
2582
|
+
// src/commands/comment.ts
|
|
2583
|
+
import { Command as Command10 } from "commander";
|
|
2584
|
+
var KINDS = [
|
|
2585
|
+
"comment",
|
|
2586
|
+
"tip",
|
|
2587
|
+
"report",
|
|
2588
|
+
"praise",
|
|
2589
|
+
"question"
|
|
2590
|
+
];
|
|
2591
|
+
function commentCommand() {
|
|
2592
|
+
return new Command10("comment").description("post a comment on a package").argument("<full_slug>", "package identifier {username}/{slug}").requiredOption("--body <text>", "comment body (1\u201310000 chars)").option("--kind <kind>", `top-level kind: ${KINDS.join("|")}`, "comment").option("--title <text>", "top-level post title (1\u2013140 chars)").action(
|
|
2593
|
+
async (rawSlug, opts) => {
|
|
2594
|
+
if (!KINDS.includes(opts.kind)) {
|
|
2595
|
+
throw new Error(`--kind must be one of ${KINDS.join(", ")}`);
|
|
2596
|
+
}
|
|
2597
|
+
const [username, slug] = rawSlug.split("/");
|
|
2598
|
+
if (!username || !slug) {
|
|
2599
|
+
throw new Error('full_slug must be "{username}/{slug}"');
|
|
2600
|
+
}
|
|
2601
|
+
const bundle = await useClient();
|
|
2602
|
+
if (!bundle.username) {
|
|
2603
|
+
printHuman(c.yellow("Not logged in. Run `kordis login`."));
|
|
2604
|
+
process.exitCode = 10;
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
const res = await bundle.authedRequest(
|
|
2608
|
+
(api) => api.createComment(username, slug, {
|
|
2609
|
+
kind: opts.kind,
|
|
2610
|
+
...opts.title ? { title: opts.title } : {},
|
|
2611
|
+
body: opts.body
|
|
2612
|
+
})
|
|
2613
|
+
);
|
|
2614
|
+
printDual({
|
|
2615
|
+
json: res,
|
|
2616
|
+
human: () => {
|
|
2617
|
+
printHuman(c.green("\u2713 comment posted"));
|
|
2618
|
+
printHuman(c.gray(` id: ${res.id}`));
|
|
2619
|
+
const meta = [`kind: ${res.kind}`];
|
|
2620
|
+
if (res.title) meta.push(`title: "${res.title}"`);
|
|
2621
|
+
printHuman(` ${meta.join(" \xB7 ")}`);
|
|
2622
|
+
}
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2625
|
+
);
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
// src/commands/star.ts
|
|
2629
|
+
import { Command as Command11 } from "commander";
|
|
2630
|
+
function starCommand() {
|
|
2631
|
+
return new Command11("star").description("star a package").argument("<full_slug>", "package identifier {username}/{slug}").action(async (rawSlug) => {
|
|
2632
|
+
const [username, slug] = rawSlug.split("/");
|
|
2633
|
+
if (!username || !slug) {
|
|
2634
|
+
throw new Error('full_slug must be "{username}/{slug}"');
|
|
2635
|
+
}
|
|
2636
|
+
const bundle = await useClient();
|
|
2637
|
+
if (!bundle.username) {
|
|
2638
|
+
printHuman(c.yellow("Not logged in. Run `kordis login`."));
|
|
2639
|
+
process.exitCode = 10;
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
const res = await bundle.authedRequest((api) => api.star(username, slug));
|
|
2643
|
+
printDual({
|
|
2644
|
+
json: res,
|
|
2645
|
+
human: () => {
|
|
2646
|
+
printHuman(c.green(`\u2605 starred ${res.full_slug}`));
|
|
2647
|
+
printHuman(c.gray(` total stars: ${res.star_count}`));
|
|
2648
|
+
}
|
|
2649
|
+
});
|
|
2650
|
+
});
|
|
2651
|
+
}
|
|
2652
|
+
function unstarCommand() {
|
|
2653
|
+
return new Command11("unstar").description("remove your star from a package").argument("<full_slug>", "package identifier {username}/{slug}").action(async (rawSlug) => {
|
|
2654
|
+
const [username, slug] = rawSlug.split("/");
|
|
2655
|
+
if (!username || !slug) {
|
|
2656
|
+
throw new Error('full_slug must be "{username}/{slug}"');
|
|
2657
|
+
}
|
|
2658
|
+
const bundle = await useClient();
|
|
2659
|
+
if (!bundle.username) {
|
|
2660
|
+
printHuman(c.yellow("Not logged in. Run `kordis login`."));
|
|
2661
|
+
process.exitCode = 10;
|
|
2662
|
+
return;
|
|
2663
|
+
}
|
|
2664
|
+
const res = await bundle.authedRequest(
|
|
2665
|
+
(api) => api.unstar(username, slug)
|
|
2666
|
+
);
|
|
2667
|
+
printDual({
|
|
2668
|
+
json: res,
|
|
2669
|
+
human: () => {
|
|
2670
|
+
printHuman(c.gray(`\u2606 unstarred ${res.full_slug}`));
|
|
2671
|
+
printHuman(c.gray(` total stars: ${res.star_count}`));
|
|
2672
|
+
}
|
|
2673
|
+
});
|
|
2674
|
+
});
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2512
2677
|
// src/index.ts
|
|
2513
2678
|
function buildProgram() {
|
|
2514
|
-
const program = new
|
|
2679
|
+
const program = new Command12("kordis").version(VERSION).description("Kordis \u2014 registry for agentic-coding packages").option("--json", "emit JSON output to stdout (default: human)", false).hook("preAction", (thisCommand) => {
|
|
2515
2680
|
const opts = thisCommand.optsWithGlobals();
|
|
2516
2681
|
if (opts.json) setJsonMode(true);
|
|
2517
2682
|
});
|
|
@@ -2523,6 +2688,9 @@ function buildProgram() {
|
|
|
2523
2688
|
program.addCommand(pullCommand());
|
|
2524
2689
|
program.addCommand(readCommand());
|
|
2525
2690
|
program.addCommand(infoCommand());
|
|
2691
|
+
program.addCommand(commentCommand());
|
|
2692
|
+
program.addCommand(starCommand());
|
|
2693
|
+
program.addCommand(unstarCommand());
|
|
2526
2694
|
program.addCommand(setupCommand());
|
|
2527
2695
|
return program;
|
|
2528
2696
|
}
|