claude-all-hands 1.0.6 → 1.0.7
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/.claude/envoy/README.md +11 -0
- package/.claude/envoy/package-lock.json +7 -0
- package/.claude/envoy/package.json +1 -0
- package/.claude/envoy/src/cli.ts +1 -0
- package/.claude/envoy/src/commands/context7.ts +176 -0
- package/.claude/skills/research-tools/SKILL.md +44 -2
- package/package.json +1 -1
package/.claude/envoy/README.md
CHANGED
|
@@ -21,6 +21,15 @@ envoy <group> --help
|
|
|
21
21
|
| `tavily extract` | Extract full content from URLs |
|
|
22
22
|
| `xai search` | X/Twitter search for community opinions, alternatives, discussions |
|
|
23
23
|
|
|
24
|
+
### Context7 (External Documentation)
|
|
25
|
+
|
|
26
|
+
| Tool | Use Case |
|
|
27
|
+
|------|----------|
|
|
28
|
+
| `context7 search` | Find library by name, returns IDs for context command |
|
|
29
|
+
| `context7 context` | Get documentation for known library (use search first) |
|
|
30
|
+
|
|
31
|
+
*Flow: search → get library ID → context with query*
|
|
32
|
+
|
|
24
33
|
### Vertex (Gemini)
|
|
25
34
|
|
|
26
35
|
| Tool | Use Case |
|
|
@@ -44,6 +53,7 @@ envoy <group> --help
|
|
|
44
53
|
- Pre-synthesized findings → `perplexity research`
|
|
45
54
|
- Raw sources for processing → `tavily search` → `tavily extract`
|
|
46
55
|
- Community opinions/alternatives → `xai search` (can build on previous findings with `--context`)
|
|
56
|
+
- Library documentation → `context7 search <lib>` → `context7 context <id> <query>`
|
|
47
57
|
|
|
48
58
|
**Vertex:**
|
|
49
59
|
- Arbitrary Gemini query → `vertex ask`
|
|
@@ -63,6 +73,7 @@ These tools read files directly and pass to external LLMs. Claude only receives
|
|
|
63
73
|
| `TAVILY_API_KEY` | tavily | Tavily API key |
|
|
64
74
|
| `VERTEX_API_KEY` | vertex | Google AI API key (Vertex Express) |
|
|
65
75
|
| `X_AI_API_KEY` | xai | xAI Grok API key |
|
|
76
|
+
| `CONTEXT7_API_KEY` | context7 | Context7 API key (upstash.com) |
|
|
66
77
|
| `ENVOY_TIMEOUT_MS` | optional | Global timeout (default: 120000) |
|
|
67
78
|
|
|
68
79
|
## Discovery
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"version": "0.1.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@google/genai": "^0.14.0",
|
|
12
|
+
"@upstash/context7-sdk": "^0.3.0",
|
|
12
13
|
"@visheratin/tokenizers-node": "0.1.5",
|
|
13
14
|
"@visheratin/web-ai-node": "^1.4.5",
|
|
14
15
|
"chokidar": "^5.0.0",
|
|
@@ -522,6 +523,12 @@
|
|
|
522
523
|
"pino": "*"
|
|
523
524
|
}
|
|
524
525
|
},
|
|
526
|
+
"node_modules/@upstash/context7-sdk": {
|
|
527
|
+
"version": "0.3.0",
|
|
528
|
+
"resolved": "https://registry.npmjs.org/@upstash/context7-sdk/-/context7-sdk-0.3.0.tgz",
|
|
529
|
+
"integrity": "sha512-kW5UV49mG9hh30sWP7nLq0mF7YHbTtfWrnm1VsT0UFW8mR6ovlYp7anobUh5qOaewSzraq9o2QyY77KVpI1twg==",
|
|
530
|
+
"license": "MIT"
|
|
531
|
+
},
|
|
525
532
|
"node_modules/@visheratin/tokenizers-node": {
|
|
526
533
|
"version": "0.1.5",
|
|
527
534
|
"resolved": "https://registry.npmjs.org/@visheratin/tokenizers-node/-/tokenizers-node-0.1.5.tgz",
|
package/.claude/envoy/src/cli.ts
CHANGED
|
@@ -30,6 +30,7 @@ async function getInfo(
|
|
|
30
30
|
TAVILY_API_KEY: process.env.TAVILY_API_KEY ? "set" : "missing",
|
|
31
31
|
VERTEX_API_KEY: process.env.VERTEX_API_KEY ? "set" : "missing",
|
|
32
32
|
X_AI_API_KEY: process.env.X_AI_API_KEY ? "set" : "missing",
|
|
33
|
+
CONTEXT7_API_KEY: process.env.CONTEXT7_API_KEY ? "set" : "missing",
|
|
33
34
|
},
|
|
34
35
|
timeout_ms: process.env.ENVOY_TIMEOUT_MS ?? "120000",
|
|
35
36
|
},
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context7 API commands - library documentation search and context retrieval.
|
|
3
|
+
*
|
|
4
|
+
* Flow: search (find library) → context (get docs for known library)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import { BaseCommand, type CommandResult } from "./base.js";
|
|
9
|
+
import { Context7, Context7Error, type Library } from "@upstash/context7-sdk";
|
|
10
|
+
|
|
11
|
+
/** Shared base for Context7 commands - DRY for auth + error handling */
|
|
12
|
+
abstract class Context7BaseCommand extends BaseCommand {
|
|
13
|
+
protected requireApiKey(): CommandResult | Context7 {
|
|
14
|
+
const apiKey = process.env.CONTEXT7_API_KEY;
|
|
15
|
+
if (!apiKey) {
|
|
16
|
+
return this.error("auth_error", "CONTEXT7_API_KEY not set");
|
|
17
|
+
}
|
|
18
|
+
return new Context7({ apiKey });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected async withTimeout<T>(fn: () => Promise<T>): Promise<[T, number]> {
|
|
22
|
+
const start = performance.now();
|
|
23
|
+
const timeout = new Promise<never>((_, reject) =>
|
|
24
|
+
setTimeout(() => reject(new Error("timeout")), this.timeoutMs)
|
|
25
|
+
);
|
|
26
|
+
const result = await Promise.race([fn(), timeout]);
|
|
27
|
+
return [result, Math.round(performance.now() - start)];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
protected handleError(e: unknown, extraHint?: string): CommandResult {
|
|
31
|
+
if (e instanceof Context7Error) {
|
|
32
|
+
return this.error("api_error", e.message, extraHint);
|
|
33
|
+
}
|
|
34
|
+
if (e instanceof Error && e.message.includes("timeout")) {
|
|
35
|
+
return this.error("timeout", `Request timed out after ${this.timeoutMs}ms`);
|
|
36
|
+
}
|
|
37
|
+
return this.error("api_error", e instanceof Error ? e.message : String(e));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class Context7SearchCommand extends Context7BaseCommand {
|
|
42
|
+
readonly name = "search";
|
|
43
|
+
readonly description = "Search for libraries by name, returns IDs for context command";
|
|
44
|
+
|
|
45
|
+
defineArguments(cmd: Command): void {
|
|
46
|
+
cmd
|
|
47
|
+
.argument("<library>", "Library name to search (e.g., react, fastify)")
|
|
48
|
+
.argument("[query]", "Optional query for relevance ranking")
|
|
49
|
+
.option("--limit <n>", "Max results (default: 5)", parseInt);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async execute(args: Record<string, unknown>): Promise<CommandResult> {
|
|
53
|
+
const clientOrError = this.requireApiKey();
|
|
54
|
+
if ("status" in clientOrError) return clientOrError;
|
|
55
|
+
|
|
56
|
+
const library = args.library as string;
|
|
57
|
+
const query = (args.query as string) ?? `How to use ${library}`;
|
|
58
|
+
const limit = (args.limit as number) ?? 5;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const [libraries, durationMs] = await this.withTimeout(() =>
|
|
62
|
+
clientOrError.searchLibrary(query, library)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
if (!Array.isArray(libraries)) {
|
|
66
|
+
return this.error("api_error", "Unexpected response format from Context7");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const results = libraries.slice(0, limit).map((lib: Library) => ({
|
|
70
|
+
id: lib.id, // Required for context command
|
|
71
|
+
name: lib.name,
|
|
72
|
+
description: lib.description,
|
|
73
|
+
snippets: lib.totalSnippets,
|
|
74
|
+
trust: lib.trustScore,
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
return this.success(
|
|
78
|
+
{
|
|
79
|
+
query: library,
|
|
80
|
+
results,
|
|
81
|
+
usage: results.length > 0
|
|
82
|
+
? `Use: envoy context7 context "${results[0].id}" "your question"`
|
|
83
|
+
: undefined,
|
|
84
|
+
...(results.length === 0 && {
|
|
85
|
+
suggestion: "Library not found. Try different search term or library may not be indexed.",
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
result_count: results.length,
|
|
90
|
+
command: "context7 search",
|
|
91
|
+
duration_ms: durationMs,
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
return this.handleError(e);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class Context7ContextCommand extends Context7BaseCommand {
|
|
101
|
+
readonly name = "context";
|
|
102
|
+
readonly description = "Get documentation context for a known library (use search first)";
|
|
103
|
+
|
|
104
|
+
defineArguments(cmd: Command): void {
|
|
105
|
+
cmd
|
|
106
|
+
.argument("<libraryId>", "Library ID from search (e.g., /facebook/react)")
|
|
107
|
+
.argument("<query>", "What you need docs for (e.g., 'hooks usage')")
|
|
108
|
+
.option("--text", "Return plain text instead of JSON (better for direct LLM use)");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async execute(args: Record<string, unknown>): Promise<CommandResult> {
|
|
112
|
+
const clientOrError = this.requireApiKey();
|
|
113
|
+
if ("status" in clientOrError) return clientOrError;
|
|
114
|
+
|
|
115
|
+
const libraryId = args.libraryId as string;
|
|
116
|
+
const query = args.query as string;
|
|
117
|
+
const useText = args.text as boolean;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
if (useText) {
|
|
121
|
+
// Plain text mode - directly usable in LLM prompts
|
|
122
|
+
const [content, durationMs] = await this.withTimeout(() =>
|
|
123
|
+
clientOrError.getContext(query, libraryId, { type: "txt" })
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
return this.success(
|
|
127
|
+
{
|
|
128
|
+
library: libraryId,
|
|
129
|
+
query,
|
|
130
|
+
content,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
format: "text",
|
|
134
|
+
command: "context7 context",
|
|
135
|
+
duration_ms: durationMs,
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// JSON mode - structured docs
|
|
141
|
+
const [docs, durationMs] = await this.withTimeout(() =>
|
|
142
|
+
clientOrError.getContext(query, libraryId, { type: "json" })
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (!Array.isArray(docs)) {
|
|
146
|
+
return this.error("api_error", "Unexpected response format from Context7");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const documentation = docs.map((doc) => ({
|
|
150
|
+
title: doc.title,
|
|
151
|
+
content: doc.content,
|
|
152
|
+
source: doc.source,
|
|
153
|
+
}));
|
|
154
|
+
|
|
155
|
+
return this.success(
|
|
156
|
+
{
|
|
157
|
+
library: libraryId,
|
|
158
|
+
query,
|
|
159
|
+
docs: documentation,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
doc_count: documentation.length,
|
|
163
|
+
command: "context7 context",
|
|
164
|
+
duration_ms: durationMs,
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
return this.handleError(e, "Ensure libraryId is valid (from search results)");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const COMMANDS = {
|
|
174
|
+
search: Context7SearchCommand,
|
|
175
|
+
context: Context7ContextCommand,
|
|
176
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: research-tools
|
|
3
|
-
description:
|
|
3
|
+
description: Use for research needs. IE "search the web", "research [topic]", "extract URL content", "find sources". Provides Tavily (search/extract), Perplexity (deep research), Grok (X/Twitter).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<objective>
|
|
7
|
-
External research capability for
|
|
7
|
+
External research capability for agents. Web search, deep research with citations, and real-time social signals via envoy commands.
|
|
8
8
|
</objective>
|
|
9
9
|
|
|
10
10
|
<quick_start>
|
|
@@ -17,6 +17,14 @@ envoy tavily search "query"
|
|
|
17
17
|
|
|
18
18
|
# Extract URL content
|
|
19
19
|
envoy tavily extract "url1" "url2"
|
|
20
|
+
|
|
21
|
+
# Library documentation search (Context7)
|
|
22
|
+
envoy context7 search "react"
|
|
23
|
+
envoy context7 search "fastify" "middleware patterns"
|
|
24
|
+
|
|
25
|
+
# Get library docs for known library (Context7)
|
|
26
|
+
envoy context7 context "/facebook/react" "hooks usage"
|
|
27
|
+
envoy context7 context "/fastify/fastify" "routing" --text
|
|
20
28
|
```
|
|
21
29
|
</quick_start>
|
|
22
30
|
|
|
@@ -25,6 +33,7 @@ envoy tavily extract "url1" "url2"
|
|
|
25
33
|
- GitHub content: use `gh` CLI instead of extract
|
|
26
34
|
- All commands return JSON - parse `data.content` or `data.results`
|
|
27
35
|
- Use TODAY's date for time-sensitive queries: `date +%Y-%m-%d`
|
|
36
|
+
- Context7 requires search → context flow (search gives libraryId for context)
|
|
28
37
|
</constraints>
|
|
29
38
|
|
|
30
39
|
<workflow>
|
|
@@ -35,6 +44,7 @@ Clarify: What to learn? What for? Depth needed?
|
|
|
35
44
|
<step name="choose_tool">
|
|
36
45
|
| Need | Tool | Cost |
|
|
37
46
|
|------|------|------|
|
|
47
|
+
| Library docs (known library) | `context7 search` → `context7 context` | Low |
|
|
38
48
|
| Broad question, synthesis | `perplexity research` | High |
|
|
39
49
|
| Synthesis + real-time validation | `perplexity research --grok-challenge` | Higher |
|
|
40
50
|
| X/Twitter community insights | `xai search` | Medium |
|
|
@@ -50,6 +60,12 @@ All tools return JSON. Parse `data.content` or `data.results` for findings.
|
|
|
50
60
|
<examples>
|
|
51
61
|
<command_reference>
|
|
52
62
|
```bash
|
|
63
|
+
# Context7 (library documentation)
|
|
64
|
+
envoy context7 search "react" # Find react libraries
|
|
65
|
+
envoy context7 search "fastify" "middleware handling" # Search with query context
|
|
66
|
+
envoy context7 context "/facebook/react" "hooks" # Get docs (JSON)
|
|
67
|
+
envoy context7 context "/facebook/react" "hooks" --text # Get docs (plain text)
|
|
68
|
+
|
|
53
69
|
# Perplexity (deep research)
|
|
54
70
|
envoy perplexity research "query"
|
|
55
71
|
envoy perplexity research "query" --grok-challenge
|
|
@@ -72,13 +88,36 @@ gh issue view {number} --repo {owner}/{repo}
|
|
|
72
88
|
<decision_tree>
|
|
73
89
|
```
|
|
74
90
|
Need information?
|
|
91
|
+
├─ How does library X work? → context7 search "X" → context7 context "<id>" "question"
|
|
92
|
+
├─ Library docs for codebase dependency? → context7 search → context7 context
|
|
75
93
|
├─ Know exact URL? → tavily extract
|
|
76
94
|
├─ Need to find sources? → tavily search → extract promising URLs
|
|
77
95
|
├─ Tech research for planning? → perplexity research --grok-challenge
|
|
96
|
+
├─ Implementation patterns/best practices? → perplexity research
|
|
78
97
|
└─ Quick answer, no validation? → perplexity research
|
|
79
98
|
```
|
|
80
99
|
</decision_tree>
|
|
81
100
|
|
|
101
|
+
<context7_flow>
|
|
102
|
+
Context7 is for library/package documentation. Two-step flow:
|
|
103
|
+
|
|
104
|
+
1. **Search**: Find the library and get its ID
|
|
105
|
+
```bash
|
|
106
|
+
envoy context7 search "react"
|
|
107
|
+
# Returns: { results: [{ id: "/facebook/react", name: "React", ... }] }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. **Context**: Get docs for specific questions using the ID
|
|
111
|
+
```bash
|
|
112
|
+
envoy context7 context "/facebook/react" "useState and useEffect"
|
|
113
|
+
# Returns: { docs: [{ title, content, source }] }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Tips for minimal context usage:**
|
|
117
|
+
- Use `--text` for direct LLM consumption (no JSON parsing)
|
|
118
|
+
- Be specific in query to get relevant docs only
|
|
119
|
+
</context7_flow>
|
|
120
|
+
|
|
82
121
|
<output_format>
|
|
83
122
|
```markdown
|
|
84
123
|
## Research: [Topic]
|
|
@@ -100,10 +139,13 @@ Actions based on findings.
|
|
|
100
139
|
- Skipping scope clarification before research
|
|
101
140
|
- Not parsing JSON response properly
|
|
102
141
|
- Using from non-curator/researcher agents
|
|
142
|
+
- Calling context7 context without searching first (need libraryId)
|
|
143
|
+
- Using context7 for non-library questions (use perplexity instead)
|
|
103
144
|
</anti_patterns>
|
|
104
145
|
|
|
105
146
|
<success_criteria>
|
|
106
147
|
- JSON response: `status: success` with `data` containing findings
|
|
107
148
|
- Sources/citations included for synthesis queries
|
|
108
149
|
- Content extracted for known URLs
|
|
150
|
+
- Context7: Valid libraryId used in context command
|
|
109
151
|
</success_criteria>
|