codiedev 0.5.0 → 0.5.2
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/dist/cli.js +49 -13
- package/dist/commands/push.js +38 -8
- package/dist/mcp.js +56 -15
- package/dist/utils.js +16 -7
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -62,15 +62,26 @@ Other:
|
|
|
62
62
|
codiedev docs Print the full usage guide
|
|
63
63
|
codiedev version Show version
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
The 90% workflow:
|
|
66
|
+
1. Name your file 'spec-<topic>.md' and push.
|
|
67
|
+
2. Ping a teammate to pull review.
|
|
68
|
+
3. They edit, push back. Versions stack. Done.
|
|
69
|
+
|
|
70
|
+
Other artifact types (rare — use the matching prefix):
|
|
71
|
+
review-*.md → review decision-*.md → decision
|
|
72
|
+
proposal-*.md → proposal bugfix-*.md → bugfix
|
|
73
|
+
anything else → note
|
|
74
|
+
|
|
75
|
+
Skills (slash commands):
|
|
76
|
+
Add 'name:' + 'description:' YAML frontmatter to any pushed file
|
|
77
|
+
and it shows up as /<name> in Claude Code / Codex. Filename
|
|
78
|
+
prefix doesn't matter — frontmatter is the signal.
|
|
69
79
|
|
|
70
80
|
Examples:
|
|
71
|
-
codiedev push
|
|
81
|
+
codiedev push spec-cart-clear.md # the typical case
|
|
82
|
+
codiedev push portal-design.md # with name:/description: → skill
|
|
72
83
|
codiedev pull spec-cart-clear.md
|
|
73
|
-
codiedev ping maya "thoughts
|
|
84
|
+
codiedev ping maya "thoughts?" --with spec-cart-clear.md
|
|
74
85
|
codiedev inbox --unread
|
|
75
86
|
codiedev note "idempotency key is worth a follow-up"
|
|
76
87
|
|
|
@@ -96,17 +107,23 @@ codiedev connect — link your agent CLI to CodieDev
|
|
|
96
107
|
push: `
|
|
97
108
|
codiedev push — author or update an artifact
|
|
98
109
|
|
|
99
|
-
|
|
100
|
-
codiedev push
|
|
110
|
+
Default path:
|
|
111
|
+
codiedev push spec-<topic>.md
|
|
101
112
|
|
|
102
|
-
The file's basename becomes its key (unique per company). Pushing
|
|
103
|
-
same key again
|
|
113
|
+
The file's basename becomes its key (unique per company). Pushing
|
|
114
|
+
the same key again versions it — full history is preserved.
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
Other types: rename with the matching prefix (review-*, decision-*,
|
|
117
|
+
proposal-*, bugfix-*) or pass --type. Anything else lands as 'note'.
|
|
118
|
+
|
|
119
|
+
Skills (slash commands): add 'name:' + 'description:' YAML
|
|
120
|
+
frontmatter to the top of the file. It shows up as /<name> in
|
|
121
|
+
the Skills tab. Filename prefix doesn't matter for the skill role.
|
|
106
122
|
|
|
107
123
|
Examples:
|
|
108
|
-
codiedev push spec-cart-clear.md
|
|
109
|
-
codiedev push
|
|
124
|
+
codiedev push spec-cart-clear.md # the typical case
|
|
125
|
+
codiedev push portal-design.md # with name:/description: → skill
|
|
126
|
+
codiedev push docs/review-auth.md
|
|
110
127
|
codiedev push notes/random.md --type note
|
|
111
128
|
`.trim(),
|
|
112
129
|
pull: `
|
|
@@ -244,6 +261,25 @@ Artifacts have a status that auto-advances as PRs reference them:
|
|
|
244
261
|
Artifacts stay editable at every stage, including after merge —
|
|
245
262
|
lessons-learned and follow-up notes append as new versions.
|
|
246
263
|
|
|
264
|
+
## Skills
|
|
265
|
+
|
|
266
|
+
Default path:
|
|
267
|
+
|
|
268
|
+
1. Pick a name: e.g. portal-design
|
|
269
|
+
2. Top the file with frontmatter:
|
|
270
|
+
---
|
|
271
|
+
name: portal-design
|
|
272
|
+
description: Use when reviewing or building portal UI.
|
|
273
|
+
---
|
|
274
|
+
# body...
|
|
275
|
+
3. codiedev push portal-design.md
|
|
276
|
+
|
|
277
|
+
It's now /portal-design in Claude Code / Codex.
|
|
278
|
+
|
|
279
|
+
Filename prefix is irrelevant for skills — frontmatter is the only
|
|
280
|
+
signal. The stored artifact type still follows the filename rule
|
|
281
|
+
(so a skill in a spec file is both a 'spec' and a callable skill).
|
|
282
|
+
|
|
247
283
|
## Portal
|
|
248
284
|
|
|
249
285
|
Everything you do in the CLI is visible at:
|
package/dist/commands/push.js
CHANGED
|
@@ -45,9 +45,13 @@ const VALID_TYPES = new Set([
|
|
|
45
45
|
"review",
|
|
46
46
|
"note",
|
|
47
47
|
]);
|
|
48
|
+
const VALID_KINDS = new Set(["doc", "skill"]);
|
|
48
49
|
function parseArgs(args) {
|
|
49
50
|
let file;
|
|
50
51
|
let type;
|
|
52
|
+
let kind;
|
|
53
|
+
let force = false;
|
|
54
|
+
const tags = [];
|
|
51
55
|
for (let i = 0; i < args.length; i++) {
|
|
52
56
|
const a = args[i];
|
|
53
57
|
if (a === "--type" && i + 1 < args.length) {
|
|
@@ -56,22 +60,41 @@ function parseArgs(args) {
|
|
|
56
60
|
else if (a.startsWith("--type=")) {
|
|
57
61
|
type = a.slice("--type=".length);
|
|
58
62
|
}
|
|
63
|
+
else if (a === "--kind" && i + 1 < args.length) {
|
|
64
|
+
kind = args[++i];
|
|
65
|
+
}
|
|
66
|
+
else if (a.startsWith("--kind=")) {
|
|
67
|
+
kind = a.slice("--kind=".length);
|
|
68
|
+
}
|
|
69
|
+
else if (a === "--tag" && i + 1 < args.length) {
|
|
70
|
+
tags.push(args[++i]);
|
|
71
|
+
}
|
|
72
|
+
else if (a.startsWith("--tag=")) {
|
|
73
|
+
tags.push(a.slice("--tag=".length));
|
|
74
|
+
}
|
|
75
|
+
else if (a === "--force") {
|
|
76
|
+
force = true;
|
|
77
|
+
}
|
|
59
78
|
else if (!a.startsWith("--") && !file) {
|
|
60
79
|
file = a;
|
|
61
80
|
}
|
|
62
81
|
}
|
|
63
82
|
if (!file) {
|
|
64
|
-
console.error("Usage: codiedev push <file.md> [--
|
|
83
|
+
console.error("Usage: codiedev push <file.md> [--kind doc|skill] [--tag <name>] [--force]");
|
|
65
84
|
process.exit(1);
|
|
66
85
|
}
|
|
67
86
|
if (type && !VALID_TYPES.has(type)) {
|
|
68
87
|
console.error(`Invalid --type. Valid types: ${[...VALID_TYPES].join(", ")}`);
|
|
69
88
|
process.exit(1);
|
|
70
89
|
}
|
|
71
|
-
|
|
90
|
+
if (kind && !VALID_KINDS.has(kind)) {
|
|
91
|
+
console.error(`Invalid --kind. Valid kinds: ${[...VALID_KINDS].join(", ")}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
return { file, type, kind, tags, force };
|
|
72
95
|
}
|
|
73
96
|
async function runPush(args) {
|
|
74
|
-
const { file, type } = parseArgs(args);
|
|
97
|
+
const { file, type, kind, tags, force } = parseArgs(args);
|
|
75
98
|
const config = (0, shared_1.requireConfig)();
|
|
76
99
|
let absolute = file;
|
|
77
100
|
if (!path.isAbsolute(absolute)) {
|
|
@@ -90,12 +113,19 @@ async function runPush(args) {
|
|
|
90
113
|
try {
|
|
91
114
|
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/push", {
|
|
92
115
|
config,
|
|
93
|
-
body: {
|
|
116
|
+
body: {
|
|
117
|
+
filename,
|
|
118
|
+
markdown,
|
|
119
|
+
type,
|
|
120
|
+
kind,
|
|
121
|
+
tags: tags.length > 0 ? tags : undefined,
|
|
122
|
+
force,
|
|
123
|
+
},
|
|
94
124
|
});
|
|
95
|
-
|
|
96
|
-
console.log(
|
|
97
|
-
console.log(`
|
|
98
|
-
console.log(`
|
|
125
|
+
const tagSummary = res.tags && res.tags.length > 0 ? ` tags=[${res.tags.join(", ")}]` : "";
|
|
126
|
+
console.log(`✓ Pushed ${filename} (kind=${res.kind}${tagSummary}).`);
|
|
127
|
+
console.log(` Visible under: ${res.destination}`);
|
|
128
|
+
console.log(` Pull with: codiedev pull ${filename}`);
|
|
99
129
|
}
|
|
100
130
|
catch (err) {
|
|
101
131
|
console.error(`Push failed: ${err.message}`);
|
package/dist/mcp.js
CHANGED
|
@@ -60,31 +60,56 @@ const PKG_VERSION = "0.5.0";
|
|
|
60
60
|
const TOOLS = [
|
|
61
61
|
{
|
|
62
62
|
name: "codiedev_push",
|
|
63
|
-
description: "Push
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
63
|
+
description: "Push any markdown artifact (doc or skill) to the team's CodieDev " +
|
|
64
|
+
"artifact layer so teammates can see, discuss, and run it. Works for " +
|
|
65
|
+
"specs, decisions, proposals, bugfixes, reviews, notes, AND " +
|
|
66
|
+
"Claude Code / Codex skills (files with SKILL.md frontmatter — " +
|
|
67
|
+
"`name:` and `description:` keys). Just pass the filename + markdown " +
|
|
68
|
+
"— `kind` is auto-detected from the content (skill if frontmatter, " +
|
|
69
|
+
"otherwise doc). Use when the user asks to share, push, save, or " +
|
|
70
|
+
"publish something (e.g., 'push this spec', 'save as a skill', " +
|
|
71
|
+
"'share the review'). The response says where the artifact will " +
|
|
72
|
+
"appear so you can confirm to the user.",
|
|
71
73
|
inputSchema: {
|
|
72
74
|
type: "object",
|
|
73
75
|
properties: {
|
|
74
76
|
filename: {
|
|
75
77
|
type: "string",
|
|
76
|
-
description: "Basename of the artifact file, e.g. 'spec-214.md'
|
|
77
|
-
"artifact's key for pulling
|
|
78
|
+
description: "Basename of the artifact file, e.g. 'spec-214.md' or " +
|
|
79
|
+
"'writing-emails.md'. Becomes the artifact's key for pulling " +
|
|
80
|
+
"and pinging.",
|
|
78
81
|
},
|
|
79
82
|
markdown: {
|
|
80
83
|
type: "string",
|
|
81
84
|
description: "Full markdown content of the artifact.",
|
|
82
85
|
},
|
|
86
|
+
kind: {
|
|
87
|
+
type: "string",
|
|
88
|
+
enum: ["doc", "skill"],
|
|
89
|
+
description: "Top-level kind. Auto-detected from frontmatter — leave unset " +
|
|
90
|
+
"in the common case. Pass `skill` for files with SKILL.md " +
|
|
91
|
+
"frontmatter, `doc` for everything else. If you pass a value " +
|
|
92
|
+
"that disagrees with the detected kind the push fails unless " +
|
|
93
|
+
"`force: true` is also set.",
|
|
94
|
+
},
|
|
95
|
+
tags: {
|
|
96
|
+
type: "array",
|
|
97
|
+
items: { type: "string" },
|
|
98
|
+
description: "Optional free-form tags (e.g., ['spec', 'auth']). The legacy " +
|
|
99
|
+
"type prefix from the filename is added automatically — you " +
|
|
100
|
+
"don't need to repeat it.",
|
|
101
|
+
},
|
|
102
|
+
force: {
|
|
103
|
+
type: "boolean",
|
|
104
|
+
description: "Override the kind-mismatch guard. Only pass when the user " +
|
|
105
|
+
"explicitly wants to ignore the detected kind.",
|
|
106
|
+
},
|
|
83
107
|
type: {
|
|
84
108
|
type: "string",
|
|
85
109
|
enum: ["spec", "bugfix", "decision", "proposal", "review", "note"],
|
|
86
|
-
description: "
|
|
87
|
-
"
|
|
110
|
+
description: "Legacy override for the doc-shape tag. Optional — inferred " +
|
|
111
|
+
"from the filename prefix when omitted. Prefer `tags` for new " +
|
|
112
|
+
"code.",
|
|
88
113
|
},
|
|
89
114
|
},
|
|
90
115
|
required: ["filename", "markdown"],
|
|
@@ -522,20 +547,28 @@ async function handlePush(args, config) {
|
|
|
522
547
|
const filename = asString(args.filename);
|
|
523
548
|
const markdown = asString(args.markdown);
|
|
524
549
|
const type = asStringOrUndefined(args.type);
|
|
550
|
+
const kind = asStringOrUndefined(args.kind);
|
|
551
|
+
const tags = asStringArrayOrUndefined(args.tags);
|
|
552
|
+
const force = asBoolOrUndefined(args.force);
|
|
525
553
|
if (!filename)
|
|
526
554
|
throw new Error("filename required");
|
|
527
555
|
if (!markdown)
|
|
528
556
|
throw new Error("markdown required");
|
|
557
|
+
if (kind && kind !== "doc" && kind !== "skill") {
|
|
558
|
+
throw new Error("kind must be 'doc' or 'skill' if provided");
|
|
559
|
+
}
|
|
529
560
|
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/push", {
|
|
530
561
|
config,
|
|
531
|
-
body: { filename, markdown, type },
|
|
562
|
+
body: { filename, markdown, type, kind, tags, force },
|
|
532
563
|
});
|
|
564
|
+
const tagSummary = res.tags && res.tags.length > 0 ? `, tags=[${res.tags.join(", ")}]` : "";
|
|
533
565
|
return {
|
|
534
566
|
content: [
|
|
535
567
|
{
|
|
536
568
|
type: "text",
|
|
537
|
-
text: `✓ Pushed ${filename} (
|
|
538
|
-
`
|
|
569
|
+
text: `✓ Pushed ${filename} (kind=${res.kind}${tagSummary}, version=v${res.version}, id=${res.artifactId}).\n` +
|
|
570
|
+
` Visible under: ${res.destination}\n` +
|
|
571
|
+
` Pull with: \`codiedev pull ${filename}\``,
|
|
539
572
|
},
|
|
540
573
|
],
|
|
541
574
|
};
|
|
@@ -998,6 +1031,14 @@ function asStringOrUndefined(v) {
|
|
|
998
1031
|
function asIntOrUndefined(v) {
|
|
999
1032
|
return typeof v === "number" && Number.isInteger(v) ? v : undefined;
|
|
1000
1033
|
}
|
|
1034
|
+
function asBoolOrUndefined(v) {
|
|
1035
|
+
return typeof v === "boolean" ? v : undefined;
|
|
1036
|
+
}
|
|
1037
|
+
function asStringArrayOrUndefined(v) {
|
|
1038
|
+
if (!Array.isArray(v))
|
|
1039
|
+
return undefined;
|
|
1040
|
+
return v.filter((x) => typeof x === "string");
|
|
1041
|
+
}
|
|
1001
1042
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1002
1043
|
// Main
|
|
1003
1044
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/dist/utils.js
CHANGED
|
@@ -220,13 +220,22 @@ thought, use the \`codiedev\` CLI via Bash:**
|
|
|
220
220
|
| "show my library" / "what artifacts exist?" | MCP tool \`codiedev_get_library\` |
|
|
221
221
|
| "react 🛠 to that post" / "mark as used" | MCP tool \`codiedev_react\` |
|
|
222
222
|
|
|
223
|
-
**
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
-
|
|
223
|
+
**Just push the file — we'll figure out where it goes.** Every artifact
|
|
224
|
+
is classified into one of two kinds at upload time:
|
|
225
|
+
|
|
226
|
+
- **skill** — the file has SKILL.md frontmatter (\`name:\` + \`description:\`
|
|
227
|
+
inside a \`---\` block). Lands under \`Artifacts → Skills tab\` and is
|
|
228
|
+
invokable as a slash command (\`/<name>\`).
|
|
229
|
+
- **doc** — everything else. Lands under \`Artifacts → My artifacts\`.
|
|
230
|
+
|
|
231
|
+
Detection is content-based, not filename-based. The filename prefix
|
|
232
|
+
(\`spec-\` / \`decision-\` / \`proposal-\` / \`bugfix-\` / \`review-\` /
|
|
233
|
+
\`note-\`) is preserved as a *tag* you can filter by, but it never gates
|
|
234
|
+
visibility. A SKILL-frontmatter file named \`note-foo.md\` still becomes
|
|
235
|
+
a skill.
|
|
236
|
+
|
|
237
|
+
The \`codiedev push\` response always says where the artifact landed —
|
|
238
|
+
read it back to the user so they can confirm.
|
|
230
239
|
|
|
231
240
|
**Resolving "the spec we just worked on":**
|
|
232
241
|
- If a file was recently edited in this session matching the conventions
|