@morphllm/morph-setup 1.0.0 → 1.0.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.
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-edit
|
|
3
|
+
description: Use Fast Apply (edit_file) for precise edits without reading full files.
|
|
4
|
+
metadata:
|
|
5
|
+
author: morph
|
|
6
|
+
version: "0.1.0"
|
|
7
|
+
argument-hint: <file-or-change>
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Code Edit
|
|
11
|
+
|
|
12
|
+
Prefer `edit_file` for modifications. Minimize full-file reads.
|
|
13
|
+
|
|
14
|
+
## When To Use
|
|
15
|
+
|
|
16
|
+
- The user requests code changes.
|
|
17
|
+
- You can target specific files/functions.
|
|
18
|
+
- You need to avoid context pollution.
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
1. Locate the target file(s) (WarpGrep if needed).
|
|
23
|
+
2. Read the smallest necessary snippet(s).
|
|
24
|
+
3. Use `edit_file` with minimal context and `// ... existing code ...` placeholders.
|
|
25
|
+
4. Re-run relevant checks (tests/build/lint) if available.
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- Keep edits small and surgical.
|
|
30
|
+
- Prefer adding one change per call.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explore
|
|
3
|
+
description: Use this skill when the user asks you something that requires searching a code base
|
|
4
|
+
metadata:
|
|
5
|
+
author: morph
|
|
6
|
+
version: "0.1.0"
|
|
7
|
+
argument-hint: <question>
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Explore
|
|
11
|
+
|
|
12
|
+
Use WarpGrep to explore a codebase, this saves time and tokens.
|
|
13
|
+
|
|
14
|
+
## When To Use
|
|
15
|
+
|
|
16
|
+
- The user asks "how does this work?" or "where is X implemented?", anything that involves reading/tracing code
|
|
17
|
+
- You need entry points, data flow, or ownership of a behavior.
|
|
18
|
+
- Keyword grep is likely to miss the relevant files.
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
1. Translate the user question into a tight semantic query.
|
|
23
|
+
2. Run `warpgrep_codebase_search` against the repo root.
|
|
24
|
+
3. Read the returned files/sections.
|
|
25
|
+
4. Summarize the flow with concrete file paths.
|
|
26
|
+
5. If changes are requested, propose the smallest edit plan and then execute.
|
|
27
|
+
|
|
28
|
+
## Query Template
|
|
29
|
+
|
|
30
|
+
"Find the entry points and data flow for <X>. Include router/handlers, config, and tests."
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: feature-research
|
|
3
|
+
description: Research existing architecture before implementing a complex feature.
|
|
4
|
+
metadata:
|
|
5
|
+
author: morph
|
|
6
|
+
version: "0.1.0"
|
|
7
|
+
argument-hint: <feature>
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Feature Research
|
|
11
|
+
|
|
12
|
+
Before implementing a complex feature, use WarpGrep to avoid duplicating patterns and to match existing conventions.
|
|
13
|
+
|
|
14
|
+
## When To Use
|
|
15
|
+
|
|
16
|
+
- New feature spans multiple modules/services.
|
|
17
|
+
- You need to find existing patterns for similar features.
|
|
18
|
+
- You need to identify API boundaries, data models, and tests.
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
1. Identify the likely "shape" of the feature (routes, state, DB, background jobs, UI).
|
|
23
|
+
2. Run `warpgrep_codebase_search` with a query that asks for similar features and related files.
|
|
24
|
+
3. Extract:
|
|
25
|
+
- Existing patterns to reuse
|
|
26
|
+
- Integration points
|
|
27
|
+
- Config/feature-flag conventions
|
|
28
|
+
- Tests to mirror
|
|
29
|
+
4. Propose an implementation plan that matches the repo.
|
|
30
|
+
5. Implement.
|
|
31
|
+
|
|
32
|
+
## Query Template
|
|
33
|
+
|
|
34
|
+
"Find existing implementations similar to <feature>. Include endpoints, data models, background tasks, and tests."
|
package/dist/index.js
CHANGED
|
@@ -925,23 +925,33 @@ async function showMorphSplash() {
|
|
|
925
925
|
process.stdout.write("\n");
|
|
926
926
|
}
|
|
927
927
|
function getBundledSkillsDir() {
|
|
928
|
-
return path3.resolve(__dirname, "..", "skills");
|
|
928
|
+
return path3.resolve(__dirname, "..", ".agents", "skills");
|
|
929
929
|
}
|
|
930
930
|
function getAllAgentTypes() {
|
|
931
931
|
return Object.keys(agents);
|
|
932
932
|
}
|
|
933
|
-
async function
|
|
934
|
-
const
|
|
933
|
+
async function selectPlatforms(opts) {
|
|
934
|
+
const supportedMcpIds = new Set(listSupportedMcpClients().map((c) => c.id));
|
|
935
|
+
const allPlatforms = getAllAgentTypes().filter((id) => supportedMcpIds.has(id));
|
|
935
936
|
if (opts.cliAgents.length > 0) return opts.cliAgents;
|
|
936
|
-
if (opts.yes)
|
|
937
|
-
|
|
938
|
-
|
|
937
|
+
if (opts.yes) {
|
|
938
|
+
const detectedAgents2 = await detectInstalledAgents();
|
|
939
|
+
const detectedMcp2 = detectMcpClients();
|
|
940
|
+
const detected2 = [.../* @__PURE__ */ new Set([...detectedAgents2, ...detectedMcp2])].filter(
|
|
941
|
+
(id) => supportedMcpIds.has(id)
|
|
942
|
+
);
|
|
943
|
+
return detected2.length > 0 ? detected2 : allPlatforms;
|
|
944
|
+
}
|
|
945
|
+
const detectedAgents = await detectInstalledAgents();
|
|
946
|
+
const detectedMcp = detectMcpClients();
|
|
947
|
+
const detected = /* @__PURE__ */ new Set([...detectedAgents, ...detectedMcp]);
|
|
948
|
+
const initial = detected.size > 0 ? [...detected] : allPlatforms;
|
|
939
949
|
const res = await p.multiselect({
|
|
940
|
-
message: "Choose which
|
|
941
|
-
options:
|
|
950
|
+
message: "Choose which platforms you want to install into:",
|
|
951
|
+
options: allPlatforms.map((id) => ({
|
|
942
952
|
value: id,
|
|
943
953
|
label: agents[id].displayName,
|
|
944
|
-
hint: detected.
|
|
954
|
+
hint: detected.has(id) ? "detected" : void 0
|
|
945
955
|
})),
|
|
946
956
|
initialValues: initial,
|
|
947
957
|
required: true
|
|
@@ -949,25 +959,6 @@ async function selectAgents(opts) {
|
|
|
949
959
|
if (p.isCancel(res)) process.exit(0);
|
|
950
960
|
return res;
|
|
951
961
|
}
|
|
952
|
-
async function selectMcpClients(opts) {
|
|
953
|
-
const supported = listSupportedMcpClients();
|
|
954
|
-
const detected = detectMcpClients();
|
|
955
|
-
if (opts.yes) {
|
|
956
|
-
return detected.length > 0 ? detected : supported.map((c) => c.id);
|
|
957
|
-
}
|
|
958
|
-
const res = await p.multiselect({
|
|
959
|
-
message: "Choose which apps to install the MCP into",
|
|
960
|
-
options: supported.map((c) => ({
|
|
961
|
-
value: c.id,
|
|
962
|
-
label: c.label,
|
|
963
|
-
hint: detected.includes(c.id) ? "detected" : void 0
|
|
964
|
-
})),
|
|
965
|
-
initialValues: detected.length > 0 ? detected : supported.map((c) => c.id),
|
|
966
|
-
required: true
|
|
967
|
-
});
|
|
968
|
-
if (p.isCancel(res)) process.exit(0);
|
|
969
|
-
return res;
|
|
970
|
-
}
|
|
971
962
|
async function getMorphMcpInput(opts) {
|
|
972
963
|
const envApiKey = process.env.MORPH_API_KEY;
|
|
973
964
|
const effectiveApiKey = opts.cliApiKey ?? envApiKey;
|
|
@@ -1037,22 +1028,23 @@ async function main() {
|
|
|
1037
1028
|
const pkg = require2("../package.json");
|
|
1038
1029
|
setVersion(pkg.version);
|
|
1039
1030
|
await showMorphSplash();
|
|
1040
|
-
const program = new Command().name("morph-setup").description("Install Morph MCP and bundled skills onto coding agents").argument("[source]", "Optional skills source (repo/path). Bundled skills are always installed.").option("--morph-api-key <key>", "MORPH_API_KEY to write into MCP config (overrides env)").option("-g, --global", "Install skills globally (default)").option("
|
|
1031
|
+
const program = new Command().name("morph-setup").description("Install Morph MCP and bundled skills onto coding agents").argument("[source]", "Optional skills source (repo/path). Bundled skills are always installed.").option("--morph-api-key <key>", "MORPH_API_KEY to write into MCP config (overrides env)").option("-g, --global", "Install skills globally (default)").option("-a, --agent <agents...>", "Target specific agents (repeatable)").option("-s, --skill <skills...>", "Install specific skills by name (only affects <source> skills)").option("-l, --list", "List available skills without installing").option("-y, --yes", "Skip all confirmation prompts").version(pkg.version);
|
|
1041
1032
|
const argv = process.argv.slice();
|
|
1042
1033
|
if (argv[2] === "--") argv.splice(2, 1);
|
|
1043
1034
|
program.parse(argv);
|
|
1044
1035
|
const opts = program.opts();
|
|
1045
1036
|
const source = program.args[0];
|
|
1046
1037
|
const yes = !!opts.yes;
|
|
1047
|
-
const global =
|
|
1038
|
+
const global = true;
|
|
1048
1039
|
p.intro(chalk.greenBright(" Morph MCP Install "));
|
|
1049
|
-
const mcpClients = await selectMcpClients({ yes });
|
|
1050
1040
|
const mcpInput = await getMorphMcpInput({
|
|
1051
1041
|
yes,
|
|
1052
1042
|
cliApiKey: opts.morphApiKey
|
|
1053
1043
|
});
|
|
1054
1044
|
const cliAgents = (opts.agent ?? []).map((a) => a);
|
|
1055
|
-
const
|
|
1045
|
+
const selectedPlatforms = await selectPlatforms({ yes, cliAgents });
|
|
1046
|
+
const mcpClients = selectedPlatforms;
|
|
1047
|
+
const targetAgents = selectedPlatforms;
|
|
1056
1048
|
if (opts.list) {
|
|
1057
1049
|
const bundled = await discoverSkills(getBundledSkillsDir());
|
|
1058
1050
|
p.log.info(chalk.greenBright("Bundled skills:"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morphllm/morph-setup",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Install Morph MCP and bundled skills onto coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
-
"
|
|
14
|
+
".agents",
|
|
15
15
|
"README.md"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|