From 706bbf79748631495846451c33002908d8ec9945 Mon Sep 17 00:00:00 2001 From: Vinod Muthusamy Date: Fri, 30 Jan 2026 13:55:35 -0600 Subject: [PATCH] feat: add save skill and improve kaizen plugin - Add save skill for capturing session workflows as reusable skills - Remove deprecated Stop hook from README - Fix duplicate step numbering in SAVE_SKILL_DESIGN.md - Remove user-specific paths from documentation and test data Co-Authored-By: Claude (aws/claude-opus-4-5) --- SAVE_SKILL_DESIGN.md | 819 ++++++++++++++++++ plugins/kaizen/INSTALL.md | 109 --- plugins/kaizen/README.md | 69 +- plugins/kaizen/SAVE_SKILL.md | 291 +++++++ plugins/kaizen/hooks/hooks.json | 13 +- plugins/kaizen/scripts/retrieve_guidelines.py | 22 +- .../{guideline-generator => learn}/SKILL.md | 50 +- .../{guideline-retrieval => recall}/SKILL.md | 7 +- plugins/kaizen/skills/save/SKILL.md | 470 ++++++++++ tests/data/trajectory.json | 16 +- 10 files changed, 1708 insertions(+), 158 deletions(-) create mode 100644 SAVE_SKILL_DESIGN.md delete mode 100644 plugins/kaizen/INSTALL.md create mode 100644 plugins/kaizen/SAVE_SKILL.md rename plugins/kaizen/skills/{guideline-generator => learn}/SKILL.md (69%) rename plugins/kaizen/skills/{guideline-retrieval => recall}/SKILL.md (82%) create mode 100644 plugins/kaizen/skills/save/SKILL.md diff --git a/SAVE_SKILL_DESIGN.md b/SAVE_SKILL_DESIGN.md new file mode 100644 index 00000000..789db0e6 --- /dev/null +++ b/SAVE_SKILL_DESIGN.md @@ -0,0 +1,819 @@ +# Save Session as Skill - Design Document + +## Overview + +This skill enables users to capture successful workflows from their current session and save them as reusable skills. It analyzes the session trajectory (user requests, tool calls, reasoning steps) and generates a new skill document that can be invoked in future sessions. + +## Key Concepts + +- **Session Trajectory**: The complete conversation history including user messages, assistant reasoning, tool calls, and tool responses +- **Workflow Pattern**: The sequence of steps and tools used to accomplish a task +- **Parameterization**: Identifying session-specific values that should become parameters in the new skill +- **Skill Template**: The generated SKILL.md file that captures the workflow + +## Architecture Flow + +1. User completes a successful task/workflow in their session +2. User invokes the "save-session-as-skill" skill +3. Skill analyzes the current session trajectory to extract: + - User's original request/goal + - Sequence of reasoning steps + - Tool calls made (with arguments) + - Tool responses and outcomes + - Final result/output +4. Skill identifies parameterizable values (file paths, names, specific data) +5. Skill generates a new SKILL.md document with: + - Clear description of what the skill does + - Step-by-step workflow instructions + - Parameter placeholders for customizable values + - Examples of usage +6. Skill prompts user for the new skill name +7. Skill saves the new skill to the appropriate directory +8. Skill provides summary of what was saved and where + +## Workflow Design + +### Step 1: Analyze Current Session + +**Input**: Current session trajectory (available via environment or Phoenix) + +**Process**: +- Extract all user messages to understand the task goal +- Extract all assistant reasoning/thinking to understand the approach +- Extract all tool calls to understand the actions taken +- Extract all tool responses to understand what worked +- Identify the final successful outcome + +**Output**: Structured analysis of the session + +### Step 2: Identify Workflow Pattern + +**Process**: +- Group related tool calls into logical steps +- Identify decision points and conditional logic +- Recognize error handling and recovery patterns +- Extract the high-level workflow sequence + +**Example Pattern Recognition**: +``` +User Request: "Read states.txt and list my teammates' locations" + +Workflow Pattern Identified: +1. Attempt to read file at expected location +2. If access denied, check allowed directories +3. Search for file in allowed directories +4. Read file from correct location +5. Parse and format the results +``` + +### Step 3: Parameterize Session-Specific Values + +**Process**: +- Identify values that are specific to this session: + - File paths (e.g., `/home/user/...` → `{file_path}`) + - File names (e.g., `states.txt` → `{filename}`) + - Specific data values (e.g., `texas` → `{state_name}`) + - Directory paths (e.g., `cuga_workspace` → `{workspace_dir}`) + +**Parameterization Rules**: +- Absolute paths → relative or parameterized +- User-specific names → generic placeholders +- Specific data → parameter with description +- Keep tool names and general patterns unchanged + +**Example**: +``` +Original: "Read /home/user/workspace/my-agent/cuga_workspace/states.txt" +Parameterized: "Read {workspace_dir}/{filename}" +``` + +### Step 4: Generate Skill Document + +**Template Structure**: +```markdown +--- +name: {skill-name} +description: {one-line description of what this skill does} +--- + +# {Skill Title} + +## Overview + +{Brief description of the skill's purpose and when to use it} + +## Parameters + +{List of parameters the user needs to provide} + +- **{param_name}**: {description of parameter} +- **{param_name}**: {description of parameter} + +## Workflow + +### Step 1: {Step Name} + +{Description of what this step does} + +**Action**: {Tool or approach to use} + +**Example**: +``` +{Example command or tool call} +``` + +### Step 2: {Step Name} + +{Continue for each step...} + +## Error Handling + +{Common errors and how to handle them} + +## Examples + +### Example 1: {Use Case} + +**Input**: +- {param}: {value} +- {param}: {value} + +**Expected Output**: +{What the user should see} + +## Notes + +{Any additional context or tips} +``` + +### Step 5: Prompt User for Skill Name + +**Process**: +- Ask user: "What would you like to name this skill?" +- Validate name (lowercase, hyphens, no spaces) +- Suggest a name based on the workflow if user is unsure + +**Example Suggestions**: +- "read-file-from-workspace" +- "search-and-read-file" +- "list-teammate-locations" + +### Step 6: Generate Helper Scripts (New) + +**When to Generate Scripts**: +Analyze the workflow to determine if helper scripts would be beneficial: + +- Data transformation or parsing (JSON, CSV, XML processing) +- File operations (reading, writing, searching, filtering) +- API calls or HTTP requests +- Complex calculations or data analysis +- Repetitive operations that could be automated +- Integration with external tools or services + +**Script Template**: +```python +#!/usr/bin/env python3 +""" +{Script description} + +Usage: + python3 {script_name}.py [arguments] + +Arguments: + {arg1}: {description} + {arg2}: {description} +""" + +import sys +import json +import argparse +from pathlib import Path + + +def main(): + """Main function implementing the script logic.""" + parser = argparse.ArgumentParser(description="{Script description}") + parser.add_argument("{arg1}", help="{description}") + parser.add_argument("{arg2}", help="{description}", nargs="?") + + args = parser.parse_args() + + # Implementation based on workflow pattern + try: + # Core logic here + result = process_data(args.{arg1}) + print(json.dumps(result, indent=2)) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def process_data(input_data): + """Process the input data according to the workflow pattern.""" + # Implementation extracted from session workflow + pass + + +if __name__ == "__main__": + main() +``` + +### Step 7: Save Skill + +**Process**: +- Create skill directory: `~/.claude/skills/{skill-name}/` +- Save SKILL.md to: `~/.claude/skills/{skill-name}/SKILL.md` +- If scripts were generated: + - Create directory: `~/.claude/skills/{skill-name}/scripts/` + - Write each script to: `~/.claude/skills/{skill-name}/scripts/{script_name}.py` + - Make scripts executable: `chmod +x ~/.claude/skills/{skill-name}/scripts/*.py` + +**Directory Structure**: +``` +~/.claude/skills/{skill-name}/ +├── SKILL.md +└── scripts/ (if applicable) + ├── script1.py + └── script2.py +``` + +**Validation**: +- Check if skill name already exists +- Prompt user to overwrite or choose different name + +### Step 8: Provide Summary + +**Output to User**: +``` +✅ Skill saved successfully! + +Skill Name: {skill-name} +Location: /home/user/workspace/kaizen/skills/{skill-name}/SKILL.md + +Summary: +{Brief description of what the skill does} + +The skill captures the following workflow: +1. {Step 1 summary} +2. {Step 2 summary} +3. {Step 3 summary} + +Parameters: +- {param1}: {description} +- {param2}: {description} + +To use this skill in the future, simply reference it by name: "{skill-name}" +``` + +## Implementation Considerations + +### Accessing Session Trajectory + +**Session Context is Already Available** + +When the skill is invoked, the session history is already available in the context. The skill simply needs to parse this context, which includes: + +- **User utterances**: All messages from the user +- **Agent reasoning steps**: Thinking tags and internal reasoning +- **Tool calls**: All tool invocations with their arguments +- **Agent responses**: All assistant messages and outputs + +**No External Fetching Required**: +- No need to call Phoenix or extract_trajectories.py +- No need to check environment variables +- Context is provided automatically when skill is invoked + +**Implementation Approach**: +The skill will include instructions to: +1. Review the conversation history in the current context +2. Extract relevant patterns from user messages, tool calls, and reasoning +3. Identify the workflow that led to success +4. Generate the parameterized skill document + +### Skill Storage Location + +**Primary Location**: `/skills/{skill-name}/SKILL.md` + +**Alternative Locations**: +- User's project-specific skills: `.claude/skills/{skill-name}/SKILL.md` +- Plugin skills: `/plugins/kaizen/skills/{skill-name}/SKILL.md` + +### Parameterization Strategy + +**Conservative Approach** (Recommended): +- Only parameterize obvious session-specific values +- Keep most of the workflow concrete +- User can manually edit the skill later for more customization + +**Aggressive Approach**: +- Parameterize many values +- Create more flexible but complex skills +- May require more user input upfront + +## Example: From Session to Skill + +### Original Session + +**User Request**: +``` +"What states do I have teammates in? Read the list from the states.txt file. use the filesystem mcp tool" +``` + +**Session Trajectory**: +1. Assistant attempts to read `/home/user/workspace/my-agent/states.txt` +2. Tool returns error: "Access denied: file is outside allowed directories" +3. Assistant calls `list_allowed_directories` to check permissions +4. Tool returns: `/home/user/workspace/my-agent/cuga_workspace` +5. Assistant searches for file in allowed directory using `search_files` +6. Tool finds: `/home/user/workspace/my-agent/cuga_workspace/states.txt` +7. Assistant reads file from correct location +8. Tool returns: "texas\nnew york\nmassachusetts\n" +9. Assistant formats and presents results to user + +**Outcome**: Successfully read file and listed teammate locations + +### Generated Skill + +```markdown +--- +name: read-file-with-permission-check +description: Read a file from workspace, handling permission errors by checking allowed directories and searching for the file +--- + +# Read File with Permission Check + +## Overview + +This skill reads a text file from a workspace directory, automatically handling permission errors by checking allowed directories and searching for the file in the correct location. Useful when file locations are uncertain or when working with MCP filesystem tools that have directory restrictions. + +## Parameters + +- **filename**: The name of the file to read (e.g., "states.txt", "config.json") +- **workspace_name**: The name of the workspace directory (e.g., "cuga_workspace") +- **expected_path**: (Optional) The initial path to try reading from + +## Workflow + +### Step 1: Attempt Initial Read + +Try to read the file from the expected location. + +**Action**: Use `mcp__filesystem__read_text_file` + +**Example**: +``` +mcp__filesystem__read_text_file({ + "path": "{expected_path}/{filename}" +}) +``` + +### Step 2: Handle Permission Error + +If access is denied, check what directories are allowed. + +**Action**: Use `mcp__filesystem__list_allowed_directories` + +**Example**: +``` +mcp__filesystem__list_allowed_directories({}) +``` + +### Step 3: Search for File + +Search for the file in the allowed directories. + +**Action**: Use `mcp__filesystem__search_files` + +**Example**: +``` +mcp__filesystem__search_files({ + "path": "{allowed_directory}", + "pattern": "{filename}" +}) +``` + +### Step 4: Read from Correct Location + +Read the file from the location found in the search. + +**Action**: Use `mcp__filesystem__read_text_file` + +**Example**: +``` +mcp__filesystem__read_text_file({ + "path": "{found_path}" +}) +``` + +### Step 5: Parse and Present Results + +Parse the file contents and present them to the user in a clear format. + +## Error Handling + +**File Not Found**: +- If search returns no results, inform user the file doesn't exist in allowed directories +- Suggest checking the filename or workspace location + +**Multiple Files Found**: +- If search returns multiple matches, list all locations +- Ask user which one to read + +**Empty File**: +- If file is empty, inform user clearly +- Don't treat as an error + +## Examples + +### Example 1: Reading Team Locations + +**Input**: +- filename: "states.txt" +- workspace_name: "cuga_workspace" +- expected_path: "/home/user/workspace/my-agent" + +**Workflow**: +1. Try to read from expected path → Access denied +2. Check allowed directories → `/home/user/workspace/my-agent/cuga_workspace` +3. Search for "states.txt" in allowed directory → Found +4. Read file → "texas\nnew york\nmassachusetts\n" +5. Present: "You have teammates in: Texas, New York, Massachusetts" + +**Expected Output**: +``` +You have teammates in: +- Texas +- New York +- Massachusetts +``` + +### Example 2: Reading Configuration File + +**Input**: +- filename: "config.json" +- workspace_name: "project_workspace" + +**Expected Output**: +```json +{ + "setting1": "value1", + "setting2": "value2" +} +``` + +## Notes + +- This pattern is particularly useful with MCP filesystem tools that have directory restrictions +- Always check allowed directories first if you encounter permission errors +- The search step helps locate files even when the exact path is unknown +- Consider caching the allowed directories list if making multiple file operations +``` + +### Comparison: Session vs Skill + +| Aspect | Original Session | Generated Skill | +|--------|-----------------|-----------------| +| **Specificity** | Hardcoded paths: `/home/user/workspace/my-agent/states.txt` | Parameterized: `{expected_path}/{filename}` | +| **Error Handling** | Reactive: encountered error, then adapted | Proactive: anticipates permission errors | +| **Reusability** | Single use case: reading states.txt | General pattern: reading any file with permission handling | +| **Documentation** | Implicit in conversation | Explicit workflow steps and examples | +| **Tool Calls** | Specific arguments | Template arguments with placeholders | + +## Design Decisions (User Confirmed) + +1. **Parameterization Level**: **Conservative** + - Only parameterize obvious session-specific values (file paths, specific names, user data) + - Keep tool names, general patterns, and workflow structure concrete + - User can manually edit the skill later for more customization + +2. **Skill Location**: **~/.claude/skills/{skill-name}/** + - Save to user's home directory under .claude/skills + - Makes skills available across all projects + - Path: `~/.claude/skills/{skill-name}/SKILL.md` + - If scripts generated: `~/.claude/skills/{skill-name}/scripts/*.py` + +3. **Skill Format**: **SKILL.md + Helper Scripts** + - Generate comprehensive SKILL.md documentation + - Include workflow steps, parameters, examples, and error handling + - **NEW**: Generate Python helper scripts for programmatic operations + - Scripts are optional - only generated when workflow includes data processing, file operations, API calls, etc. + +4. **Validation**: **No automatic validation** + - Generate and save the skill directly + - User will review and test the skill when they use it + - Faster workflow, user has full control + +## Helper Script Examples + +### Example 1: File Parser Script + +**Use Case**: Workflow involves reading and parsing a structured file + +```python +#!/usr/bin/env python3 +""" +Parse a text file and convert to JSON format. + +Usage: + python3 parse_file.py [--format json|csv] + +Arguments: + input_file: Path to the file to parse + --format: Output format (default: json) +""" + +import sys +import json +import argparse +from pathlib import Path + + +def main(): + parser = argparse.ArgumentParser(description="Parse file and convert to JSON") + parser.add_argument("input_file", help="Path to the input file") + parser.add_argument("--format", choices=["json", "csv"], default="json", + help="Output format") + + args = parser.parse_args() + + try: + data = parse_file(args.input_file) + + if args.format == "json": + print(json.dumps(data, indent=2)) + elif args.format == "csv": + print_csv(data) + + except FileNotFoundError: + print(f"Error: File not found: {args.input_file}", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def parse_file(filepath): + """Parse the input file and return structured data.""" + with open(filepath, 'r') as f: + lines = [line.strip() for line in f if line.strip()] + + return { + "items": lines, + "count": len(lines) + } + + +def print_csv(data): + """Print data in CSV format.""" + for item in data.get("items", []): + print(item) + + +if __name__ == "__main__": + main() +``` + +### Example 2: API Client Script + +**Use Case**: Workflow involves making HTTP requests to an API + +```python +#!/usr/bin/env python3 +""" +Fetch data from an API endpoint. + +Usage: + python3 api_client.py [--method GET|POST] [--data DATA] + +Arguments: + endpoint: API endpoint URL + --method: HTTP method (default: GET) + --data: JSON data for POST requests +""" + +import sys +import json +import argparse +import urllib.request +import urllib.error + + +def main(): + parser = argparse.ArgumentParser(description="API client for fetching data") + parser.add_argument("endpoint", help="API endpoint URL") + parser.add_argument("--method", choices=["GET", "POST"], default="GET", + help="HTTP method") + parser.add_argument("--data", help="JSON data for POST requests") + + args = parser.parse_args() + + try: + result = fetch_data(args.endpoint, args.method, args.data) + print(json.dumps(result, indent=2)) + except urllib.error.HTTPError as e: + print(f"HTTP Error {e.code}: {e.reason}", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def fetch_data(endpoint, method="GET", data=None): + """Fetch data from the API endpoint.""" + headers = {"Content-Type": "application/json"} + + if method == "POST" and data: + data = json.dumps(json.loads(data)).encode('utf-8') + req = urllib.request.Request(endpoint, data=data, headers=headers, method="POST") + else: + req = urllib.request.Request(endpoint, headers=headers) + + with urllib.request.urlopen(req) as response: + return json.loads(response.read().decode('utf-8')) + + +if __name__ == "__main__": + main() +``` + +### Example 3: Data Validator Script + +**Use Case**: Workflow involves validating input data + +```python +#!/usr/bin/env python3 +""" +Validate data against a schema. + +Usage: + python3 validate_data.py [--schema SCHEMA_FILE] + +Arguments: + data_file: Path to the data file to validate + --schema: Path to schema file (optional) +""" + +import sys +import json +import argparse +from pathlib import Path + + +def main(): + parser = argparse.ArgumentParser(description="Validate data against schema") + parser.add_argument("data_file", help="Path to the data file") + parser.add_argument("--schema", help="Path to schema file") + + args = parser.parse_args() + + try: + with open(args.data_file, 'r') as f: + data = json.load(f) + + if args.schema: + with open(args.schema, 'r') as f: + schema = json.load(f) + is_valid, errors = validate_with_schema(data, schema) + else: + is_valid, errors = validate_basic(data) + + if is_valid: + print(json.dumps({"valid": True, "message": "Data is valid"})) + sys.exit(0) + else: + print(json.dumps({"valid": False, "errors": errors}, indent=2)) + sys.exit(1) + + except FileNotFoundError as e: + print(f"Error: File not found: {e.filename}", file=sys.stderr) + sys.exit(1) + except json.JSONDecodeError as e: + print(f"Error: Invalid JSON: {e}", file=sys.stderr) + sys.exit(1) + + +def validate_basic(data): + """Perform basic validation checks.""" + errors = [] + + if not isinstance(data, dict): + errors.append("Data must be a JSON object") + + return len(errors) == 0, errors + + +def validate_with_schema(data, schema): + """Validate data against a schema.""" + errors = [] + + required_fields = schema.get("required", []) + for field in required_fields: + if field not in data: + errors.append(f"Missing required field: {field}") + + return len(errors) == 0, errors + + +if __name__ == "__main__": + main() +``` + +### Example 4: File Transformer Script + +**Use Case**: Workflow involves transforming file formats + +```python +#!/usr/bin/env python3 +""" +Transform file from one format to another. + +Usage: + python3 transform_file.py [--from FORMAT] [--to FORMAT] + +Arguments: + input_file: Path to the input file + output_file: Path to the output file + --from: Input format (json, csv, txt) + --to: Output format (json, csv, txt) +""" + +import sys +import json +import csv +import argparse +from pathlib import Path + + +def main(): + parser = argparse.ArgumentParser(description="Transform file formats") + parser.add_argument("input_file", help="Path to input file") + parser.add_argument("output_file", help="Path to output file") + parser.add_argument("--from", dest="from_format", default="json", + choices=["json", "csv", "txt"], + help="Input format") + parser.add_argument("--to", dest="to_format", default="json", + choices=["json", "csv", "txt"], + help="Output format") + + args = parser.parse_args() + + try: + # Read input + data = read_file(args.input_file, args.from_format) + + # Write output + write_file(args.output_file, data, args.to_format) + + print(f"Successfully transformed {args.input_file} to {args.output_file}") + + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def read_file(filepath, format_type): + """Read file in specified format.""" + if format_type == "json": + with open(filepath, 'r') as f: + return json.load(f) + elif format_type == "csv": + with open(filepath, 'r') as f: + reader = csv.DictReader(f) + return list(reader) + elif format_type == "txt": + with open(filepath, 'r') as f: + return [line.strip() for line in f if line.strip()] + + +def write_file(filepath, data, format_type): + """Write data in specified format.""" + if format_type == "json": + with open(filepath, 'w') as f: + json.dump(data, f, indent=2) + elif format_type == "csv": + if not data: + return + with open(filepath, 'w', newline='') as f: + if isinstance(data[0], dict): + writer = csv.DictWriter(f, fieldnames=data[0].keys()) + writer.writeheader() + writer.writerows(data) + else: + writer = csv.writer(f) + writer.writerows([[item] for item in data]) + elif format_type == "txt": + with open(filepath, 'w') as f: + for item in data: + f.write(f"{item}\n") + + +if __name__ == "__main__": + main() +``` + +## Next Steps + +1. ✅ Design approved by user +2. ✅ Trajectory access method confirmed (use session context) +3. Create the actual save-session-as-skill SKILL.md +4. Test the skill with the current session as an example \ No newline at end of file diff --git a/plugins/kaizen/INSTALL.md b/plugins/kaizen/INSTALL.md deleted file mode 100644 index 1ffeec60..00000000 --- a/plugins/kaizen/INSTALL.md +++ /dev/null @@ -1,109 +0,0 @@ -# Installation Guide - -## Prerequisites - -- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed -- Python 3.8+ available in PATH - -## Option 1: Load Local Plugin (Development) - -Use `--plugin-dir` to load the plugin for a session: - -```bash -# Load plugin when starting Claude Code (absolute path) -claude --plugin-dir /path/to/kaizen - -# Or use a relative path from current directory -claude --plugin-dir ./kaizen -``` - -**Note:** The plugin is loaded **for that session only**. - -### Loading Multiple Plugins - -```bash -claude --plugin-dir ./plugin1 --plugin-dir ./plugin2 -``` - -### Making It Permanent - -Add an alias to your shell profile (`~/.bashrc` or `~/.zshrc`): - -```bash -alias claude='claude --plugin-dir /path/to/kaizen' -``` - -Then reload your shell: - -```bash -source ~/.zshrc # or source ~/.bashrc -``` - -## Option 2: Install from Marketplace (when published) - -```bash -claude plugin install kaizen -``` - -## Validate Plugin - -Before using, validate the plugin manifest: - -```bash -claude plugin validate /path/to/kaizen -# Should output: ✔ Validation passed -``` - -## Initialize Guidelines File (Optional) - -```bash -mkdir -p .claude -echo '{"guidelines": []}' > .claude/guidelines.json -``` - -## Verification - -After loading the plugin, verify it's working: - -1. **Test hook execution:** - ```bash - # Start Claude Code with the plugin - claude --plugin-dir ./kaizen - - # Send any prompt, then check the debug log (in another terminal) - cat /tmp/guidelines-plugin.log - # Should show: "[retrieve] Script started" with timestamp - ``` - -2. **Test guideline storage:** - ```bash - # After ending a conversation where guidelines were generated - cat .claude/guidelines.json - # Should contain the extracted guidelines - ``` - -3. **Test skills manually:** - ```bash - # In a Claude Code session with the plugin loaded, invoke: - /guidelines:generator - /guidelines:retrieval - ``` - -## Troubleshooting - -### Plugin validation fails - -Run `claude plugin validate ./kaizen` to see specific errors. - -### Hooks not firing - -1. Verify the plugin is loaded with `--plugin-dir` -2. Verify Python is in PATH: `which python3` -3. Check script permissions: `ls -la kaizen/scripts/` -4. Check debug log: `cat /tmp/guidelines-plugin.log` - -### Guidelines not saving - -1. Verify `.claude/` directory exists in your project -2. Check write permissions on the directory -3. Review `/tmp/guidelines-plugin.log` for error messages diff --git a/plugins/kaizen/README.md b/plugins/kaizen/README.md index 5aa5dcaa..64b2da74 100644 --- a/plugins/kaizen/README.md +++ b/plugins/kaizen/README.md @@ -4,51 +4,76 @@ A plugin that helps Claude Code learn from conversations by automatically extrac ## Features -- **Automatic Learning**: At the end of each conversation, guidelines are extracted and saved -- **Context-Aware Retrieval**: At the start of each prompt, relevant guidelines are injected -- **No Manual Configuration**: Hooks are automatically installed when the plugin is enabled +- **Automatic Retrieval**: At the start of each prompt, relevant guidelines are automatically injected +- **Manual Learning**: Use the `/kaizen:learn` skill to extract and save guidelines from conversations +- **Zero-config Retrieval**: Hooks are automatically installed when the plugin is enabled ## Installation -```bash -# Load plugin for current session -claude --plugin-dir ./kaizen +### From Local Directory -# Or with absolute path -claude --plugin-dir /path/to/kaizen +```bash +claude --plugin-dir /path/to/kaizen/repo/plugins/kaizen ``` -See [INSTALL.md](INSTALL.md) for making it permanent, loading multiple plugins, and troubleshooting. +### From Marketplace + +1. Add the marketplace and plugin: + ```bash + claude plugin marketplace add AgentToolkit/kaizen + claude plugin install kaizen@kaizen-marketplace + ``` + ## How It Works -### Guideline Retrieval (UserPromptSubmit hook) +### Guideline Retrieval (Automatic) -When you submit a prompt, the plugin: +When you submit a prompt, the plugin automatically: 1. Loads all stored guidelines from `.claude/guidelines.json` 2. Formats and injects them into the conversation context 3. Claude applies relevant guidelines to the current task -### Guideline Generation (Stop hook) +### Guideline Generation (Manual by Default) -When a conversation ends, the plugin: -1. Analyzes the conversation trajectory -2. Extracts actionable guidelines from what worked/failed -3. Saves new guidelines to `.claude/guidelines.json` +By default, you must manually invoke the `/kaizen:learn` skill to extract guidelines: +1. Complete a conversation or task +2. Invoke `/kaizen:learn` +3. The plugin analyzes the conversation trajectory +4. Extracts actionable guidelines from what worked/failed +5. Saves new guidelines to `.claude/guidelines.json` ## Skills Included -### `/guidelines:generator` +### `/kaizen:learn` Manually invoke to extract guidelines from the current conversation: - Analyzes task, steps taken, successes and failures - Generates proactive guidelines (what to do, not what to avoid) - Outputs JSON for storage -### `/guidelines:retrieval` +### `/kaizen:recall` Manually invoke to retrieve and display stored guidelines. +### `/kaizen:save` + +Manually invoke to capture successful workflows from your current session and save them as reusable skills: +- Analyzes conversation history (user requests, reasoning, tool calls, responses) +- Generates parameterized SKILL.md documentation +- Creates Python helper scripts for programmatic operations (when applicable) +- Saves to `~/.claude/skills/{skill-name}/` for cross-project availability + +**Quick Start:** +``` +User: [Complete a successful task] +User: "save" +Assistant: "What would you like to name this skill?" +User: "my-workflow-name" +``` + +See [SAVE_SKILL.md](SAVE_SKILL.md) for detailed documentation. + ## Guidelines Storage Guidelines are stored in `.claude/guidelines.json`: @@ -73,7 +98,7 @@ Guidelines are stored in `.claude/guidelines.json`: ## Verification -After installation, run `claude plugin list` to confirm the plugin is enabled. See [INSTALL.md](INSTALL.md) for detailed verification steps. +After installation, run `claude plugin list` to confirm the plugin is enabled. ## Plugin Structure @@ -82,9 +107,11 @@ kaizen/ ├── .claude-plugin/ │ └── plugin.json # Plugin manifest ├── skills/ -│ ├── guideline-generator/ +│ ├── learn/ +│ │ └── SKILL.md +│ ├── recall/ │ │ └── SKILL.md -│ └── guideline-retrieval/ +│ └── save/ │ └── SKILL.md ├── hooks/ │ └── hooks.json # Auto-configured hooks diff --git a/plugins/kaizen/SAVE_SKILL.md b/plugins/kaizen/SAVE_SKILL.md new file mode 100644 index 00000000..dfcdabed --- /dev/null +++ b/plugins/kaizen/SAVE_SKILL.md @@ -0,0 +1,291 @@ +# Save Skill Documentation + +## Overview + +The **save** skill is a powerful tool that captures successful workflows from your current session and transforms them into reusable skills. It analyzes your conversation history, identifies patterns, and generates comprehensive documentation along with helper scripts. + +## Location + +The save skill is part of the Kaizen plugin: +``` +/plugins/kaizen/skills/save/SKILL.md +``` + +## What It Does + +When you invoke the `save` skill after completing a successful task, it: + +1. **Analyzes your session** - Reviews user requests, reasoning steps, tool calls, and responses +2. **Identifies patterns** - Extracts the workflow sequence and decision points +3. **Parameterizes values** - Converts session-specific values into reusable parameters +4. **Generates documentation** - Creates a comprehensive SKILL.md file +5. **Creates helper scripts** - Generates Python scripts for programmatic operations (when applicable) +6. **Saves everything** - Stores the skill in `~/.claude/skills/{skill-name}/` + +## When to Use + +Use the save skill when you: +- Complete a multi-step task successfully +- Discover a useful workflow pattern +- Want to standardize a process for future use +- Solve a problem that might recur +- Work through a complex workflow that involves data processing, file operations, or API calls + +## How to Use + +### Basic Usage + +After completing a successful task: + +``` +User: "save" +``` + +The skill will: +1. Analyze your current session +2. Ask you for a skill name +3. Generate SKILL.md and any helper scripts +4. Save to `~/.claude/skills/{skill-name}/` +5. Provide a detailed summary + +### Example Session + +``` +User: "Read the config.json file and parse it" +Assistant: [Successfully reads and parses the file] +User: "Great! save" +Assistant: "What would you like to name this skill?" +User: "read-and-parse-config" +Assistant: [Generates skill and scripts] +``` + +## Generated Output + +### Directory Structure + +``` +~/.claude/skills/{skill-name}/ +├── SKILL.md # Comprehensive documentation +└── scripts/ # Helper scripts (if applicable) + ├── parse_data.py + └── validate_data.py +``` + +### SKILL.md Contents + +The generated SKILL.md includes: +- **Overview**: What the skill does and when to use it +- **Parameters**: Required inputs with descriptions +- **Workflow**: Step-by-step instructions +- **Helper Scripts**: Documentation for any generated scripts +- **Error Handling**: Common errors and solutions +- **Examples**: Real-world usage examples +- **Notes**: Additional tips and context + +### Helper Scripts + +Scripts are automatically generated when your workflow includes: +- Data transformation or parsing (JSON, CSV, XML) +- File operations (reading, writing, searching) +- API calls or HTTP requests +- Complex calculations or data analysis +- Repetitive operations that could be automated + +## Parameterization + +The save skill uses **conservative parameterization**, meaning it only parameterizes obvious session-specific values: + +**Parameterized**: +- File paths: `/home/user/project/file.txt` → `{project_dir}/{filename}` +- Specific names: `myapp` → `{app_name}` +- User data: `john@example.com` → `{email}` + +**Kept Unchanged**: +- Tool names: `read_file`, `execute_command` +- General patterns and logic +- Error handling approaches +- Workflow structure + +## Examples + +### Example 1: File Reading Workflow + +**Session**: +``` +User: "Read states.txt using the filesystem MCP tool" +Assistant: [Handles permission errors, searches for file, reads successfully] +User: "save" +``` + +**Generated Skill**: `read-file-with-permission-check` + +**Files Created**: +``` +~/.claude/skills/read-file-with-permission-check/ +├── SKILL.md +└── scripts/ + └── search_and_read.py +``` + +### Example 2: API Integration Workflow + +**Session**: +``` +User: "Fetch user data from the API and format it" +Assistant: [Makes API call, processes response, formats output] +User: "save" +``` + +**Generated Skill**: `fetch-and-format-user-data` + +**Files Created**: +``` +~/.claude/skills/fetch-and-format-user-data/ +├── SKILL.md +└── scripts/ + ├── api_client.py + └── format_data.py +``` + +### Example 3: Simple Tool Call (No Scripts) + +**Session**: +``` +User: "List all Python files in the project" +Assistant: [Uses glob tool to find *.py files] +User: "save" +``` + +**Generated Skill**: `list-python-files` + +**Files Created**: +``` +~/.claude/skills/list-python-files/ +└── SKILL.md +``` + +## Skill Naming Guidelines + +When prompted for a skill name, follow these guidelines: + +- **Use lowercase letters**: `my-skill` not `My-Skill` +- **Separate words with hyphens**: `read-and-parse` not `read_and_parse` +- **Be descriptive**: `deploy-to-staging` not `deploy` +- **Keep it concise**: `analyze-logs` not `analyze-application-logs-for-errors` + +**Good Examples**: +- `read-file-with-permissions` +- `deploy-to-staging` +- `analyze-logs` +- `fetch-user-data` + +**Bad Examples**: +- `My Skill!` (spaces and special characters) +- `skill` (too generic) +- `read_file` (underscores instead of hyphens) + +## Handling Conflicts + +If a skill with the chosen name already exists, you'll be prompted to: +- **Overwrite** the existing skill +- **Choose a different name** +- **Cancel** the operation + +## Tips for Better Skills + +1. **Complete the task first**: Ensure your workflow is successful before saving +2. **Clear session**: The clearer your workflow, the better the generated skill +3. **Descriptive names**: Choose names that clearly indicate what the skill does +4. **Test the skill**: After saving, test it in a new session to verify it works +5. **Refine manually**: Edit the generated SKILL.md and scripts to add more context or examples + +## Advanced Usage + +### Manual Editing + +After generation, you can manually edit: +- **SKILL.md**: Add more examples, refine descriptions, update parameters +- **Scripts**: Add error handling, optimize performance, add features + +### Skill Composition + +Generated skills can reference other skills: + +```markdown +## Workflow + +### Step 1: Fetch Data +Use the `fetch-user-data` skill to retrieve user information. + +### Step 2: Process Data +Use the `parse-json-data` skill to parse the response. +``` + +### Version Control + +Consider adding your `~/.claude/skills/` directory to version control: + +```bash +cd ~/.claude/skills +git init +git add . +git commit -m "Initial skills collection" +``` + +## Troubleshooting + +### Session Too Short + +**Problem**: "Session has fewer than 3 meaningful exchanges" + +**Solution**: Complete more of the task before invoking the save skill + +### No Clear Workflow + +**Problem**: "Conversation doesn't show a clear workflow pattern" + +**Solution**: Describe the key steps you want to capture when prompted + +### Invalid Skill Name + +**Problem**: "Skill name contains invalid characters" + +**Solution**: Use lowercase letters and hyphens only (e.g., `my-skill`) + +### Script Generation Errors + +**Problem**: Script generation fails + +**Solution**: The SKILL.md will still be saved. You can add scripts manually later. + +## Technical Details + +### Session Context + +The save skill accesses the current session context, which includes: +- User utterances +- Agent reasoning (thinking tags) +- Tool calls with arguments +- Tool responses +- Agent responses + +No external fetching or Phoenix integration is required - the context is automatically available when the skill is invoked. + +### Storage Location + +Skills are saved to `~/.claude/skills/` in your home directory, making them available across all projects. + +### Script Templates + +Generated scripts follow a standard template with: +- Proper argument parsing +- Error handling +- JSON output (when appropriate) +- Usage documentation +- Executable permissions + +## Support + +For issues or questions about the save skill: +1. Review the generated SKILL.md for specific workflow questions +2. Manually edit generated skills to customize them for your needs diff --git a/plugins/kaizen/hooks/hooks.json b/plugins/kaizen/hooks/hooks.json index d2ec3fc1..33f4198c 100644 --- a/plugins/kaizen/hooks/hooks.json +++ b/plugins/kaizen/hooks/hooks.json @@ -10,17 +10,6 @@ } ] } - ], - "Stop": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/save_guidelines.py" - } - ] - } ] } -} +} \ No newline at end of file diff --git a/plugins/kaizen/scripts/retrieve_guidelines.py b/plugins/kaizen/scripts/retrieve_guidelines.py index 23b1910e..e8b4b412 100755 --- a/plugins/kaizen/scripts/retrieve_guidelines.py +++ b/plugins/kaizen/scripts/retrieve_guidelines.py @@ -18,6 +18,23 @@ def log(message): log("Script started") +# Log all environment variables +log("=== Environment Variables ===") +for key, value in sorted(os.environ.items()): + # Mask sensitive values + if any(sensitive in key.upper() for sensitive in ['PASSWORD', 'SECRET', 'TOKEN', 'KEY', 'API']): + log(f" {key}=***MASKED***") + else: + log(f" {key}={value}") +log("=== End Environment Variables ===") + +# Log command-line arguments +log("=== Command-Line Arguments ===") +log(f" sys.argv: {sys.argv}") +log(f" Script path: {sys.argv[0] if sys.argv else 'N/A'}") +log(f" Arguments: {sys.argv[1:] if len(sys.argv) > 1 else 'None'}") +log("=== End Command-Line Arguments ===") + def find_guidelines_file(): """Find the guidelines file in common locations.""" @@ -75,7 +92,10 @@ def main(): # Read input from stdin (hook provides JSON with prompt) try: input_data = json.load(sys.stdin) - log(f"Received input with keys: {list(input_data.keys())}") + log("=== Input Data ===") + log(f" Keys: {list(input_data.keys())}") + log(f" Full content: {json.dumps(input_data, indent=2)}") + log("=== End Input Data ===") except json.JSONDecodeError as e: log(f"Failed to parse JSON input: {e}") return diff --git a/plugins/kaizen/skills/guideline-generator/SKILL.md b/plugins/kaizen/skills/learn/SKILL.md similarity index 69% rename from plugins/kaizen/skills/guideline-generator/SKILL.md rename to plugins/kaizen/skills/learn/SKILL.md index 4a594337..b1f1a605 100644 --- a/plugins/kaizen/skills/guideline-generator/SKILL.md +++ b/plugins/kaizen/skills/learn/SKILL.md @@ -1,5 +1,5 @@ --- -name: guideline-generator +name: learn description: Extract actionable guidelines from conversation trajectories. Analyzes user requests, steps taken, successes and failures to generate proactive guidelines that help on similar future tasks. --- @@ -54,6 +54,54 @@ Output guidelines in the following JSON format: } ``` +### Step 4: Save Guidelines + +After generating the guidelines JSON, save them using the save_guidelines.py script: + +**Method 1: Direct Pipe (Recommended)** +```bash +echo '' | python3 ${CLAUDE_PLUGIN_ROOT}/scripts/save_guidelines.py +``` + +**Method 2: From File** +```bash +cat guidelines.json | python3 ${CLAUDE_PLUGIN_ROOT}/scripts/save_guidelines.py +``` + +**Method 3: Interactive** +```bash +python3 ${CLAUDE_PLUGIN_ROOT}/scripts/save_guidelines.py +# Then paste your JSON and press Ctrl+D +``` + +The script will: +- Find or create the guidelines file (`.claude/guidelines.json`) +- Merge new guidelines with existing ones (avoiding duplicates) +- Display confirmation with the total count + +**Example:** +```bash +echo '{ + "guidelines": [ + { + "content": "Use Python PIL/Pillow for image metadata extraction", + "rationale": "System tools may not be available in sandboxed environments", + "category": "strategy", + "trigger": "When extracting image metadata in containerized environments" + } + ] +}' | python3 ${CLAUDE_PLUGIN_ROOT}/scripts/save_guidelines.py +``` + +**Output:** +``` +Creating new file: /path/to/project/.claude/guidelines.json +Added 1 new guideline(s). Total: 1 +Guidelines stored in: /path/to/project/.claude/guidelines.json +``` + +**Note:** Guidelines are also automatically saved when a conversation ends via the Stop hook. + ## Guideline Categories - **strategy**: High-level approach or methodology choices diff --git a/plugins/kaizen/skills/guideline-retrieval/SKILL.md b/plugins/kaizen/skills/recall/SKILL.md similarity index 82% rename from plugins/kaizen/skills/guideline-retrieval/SKILL.md rename to plugins/kaizen/skills/recall/SKILL.md index fc046bd9..c0bc0999 100644 --- a/plugins/kaizen/skills/guideline-retrieval/SKILL.md +++ b/plugins/kaizen/skills/recall/SKILL.md @@ -1,5 +1,5 @@ --- -name: guideline-retrieval +name: recall description: Retrieves relevant guidelines from a knowledge base. Designed to be invoked automatically via hooks to inject context-appropriate guidelines before task execution. --- @@ -33,8 +33,3 @@ Guidelines are stored in `.claude/guidelines.json` in the project root: ] } ``` - -## Environment Variables - -- `GUIDELINES_FILE`: Optional path to guidelines JSON file (defaults to `.claude/guidelines.json`) -- `CLAUDE_PROJECT_ROOT`: Project root directory (set by Claude Code) diff --git a/plugins/kaizen/skills/save/SKILL.md b/plugins/kaizen/skills/save/SKILL.md new file mode 100644 index 00000000..6afaae8a --- /dev/null +++ b/plugins/kaizen/skills/save/SKILL.md @@ -0,0 +1,470 @@ +--- +name: save +description: Captures the current session's successful workflow and saves it as a reusable skill with SKILL.md and helper scripts +--- + +# Save Session as Skill + +## Overview + +This skill analyzes your current successful session and generates a new reusable skill with: +- **SKILL.md**: Comprehensive documentation with workflow steps, parameters, and examples +- **Helper scripts**: Python scripts for any programmatic operations identified in the workflow + +It extracts the workflow pattern from your conversation history (user requests, reasoning steps, tool calls, and responses) and creates parameterized files that can be invoked in future sessions. + +Use this skill when you've completed a task successfully and want to save the workflow for future reuse. + +## When to Use + +- After completing a multi-step task successfully +- When you've discovered a useful workflow pattern +- When you want to standardize a process for future use +- After solving a problem that might recur +- When the workflow involves programmatic operations that could benefit from helper scripts + +## Workflow + +### Step 1: Review Current Session + +Analyze the conversation history available in the current context, which includes: + +- **User messages**: All requests and questions from the user +- **Assistant reasoning**: Thinking tags and decision-making process +- **Tool calls**: All tools invoked with their arguments +- **Tool responses**: Results and outcomes from each tool +- **Final outcome**: The successful result achieved + +**Action**: Review the entire conversation from start to current point + +### Step 2: Identify the Workflow Pattern + +Extract the high-level workflow by: + +1. **Identifying the goal**: What was the user trying to accomplish? +2. **Grouping related actions**: Which tool calls belong together as logical steps? +3. **Recognizing decision points**: Where did the workflow branch based on conditions? +4. **Noting error handling**: How were errors or edge cases handled? +5. **Extracting the sequence**: What is the step-by-step process? + +**Example Pattern Recognition**: +``` +User Goal: "Read a file and display its contents" + +Workflow Pattern: +1. Attempt to read file at expected location +2. If access denied → check allowed directories +3. Search for file in allowed directories +4. Read file from correct location +5. Format and present results +``` + +### Step 3: Identify Parameterizable Values + +Apply **conservative parameterization** - only parameterize obvious session-specific values: + +**Parameterize**: +- Absolute file paths → `{file_path}` or `{directory}` +- Specific file names → `{filename}` +- User-specific data → `{data_value}` +- Project-specific names → `{project_name}` +- Workspace directories → `{workspace_dir}` + +**Keep Unchanged**: +- Tool names (e.g., `read_file`, `execute_command`) +- General patterns and logic +- Error handling approaches +- Workflow structure + +**Example**: +``` +Original: "Read /home/user/projects/myapp/config.json" +Parameterized: "Read {project_dir}/{config_file}" +``` + +### Step 4: Identify Script Opportunities + +Analyze the workflow to determine if helper scripts would be beneficial: + +**Generate scripts when the workflow includes**: +- Data transformation or parsing (JSON, CSV, XML processing) +- File operations (reading, writing, searching, filtering) +- API calls or HTTP requests +- Complex calculations or data analysis +- Repetitive operations that could be automated +- Integration with external tools or services + +**Script Types to Consider**: +- **Data processors**: Parse, transform, or validate data +- **File handlers**: Read, write, or manipulate files +- **API clients**: Interact with external services +- **Validators**: Check inputs or outputs +- **Formatters**: Convert data between formats + +**Example**: +``` +Workflow includes: Reading JSON file, extracting specific fields, formatting output +→ Generate: parse_and_format.py script +``` + +### Step 5: Generate Skill Document + +Create a new SKILL.md file with the following structure: + +```markdown +--- +name: {skill-name} +description: {one-line description of what this skill does} +--- + +# {Skill Title} + +## Overview + +{Brief description of the skill's purpose and when to use it} + +## Parameters + +{List parameters the user needs to provide} + +- **{param_name}**: {description and example} + +## Workflow + +### Step 1: {Step Name} + +{What this step does} + +**Action**: {Tool or approach to use} + +**Example**: +``` +{Example tool call or command} +``` + +{If helper script exists, reference it} +**Helper Script**: Use `scripts/{script_name}.py` for this operation + +{Repeat for each step} + +## Helper Scripts + +{If scripts were generated, document them} + +### {script_name}.py + +**Purpose**: {What the script does} + +**Usage**: +```bash +python3 ${CLAUDE_PLUGIN_ROOT}/skills/{skill-name}/scripts/{script_name}.py [arguments] +``` + +**Parameters**: +- `{param}`: {description} + +**Example**: +```bash +python3 ${CLAUDE_PLUGIN_ROOT}/skills/{skill-name}/scripts/parse_data.py input.json +``` + +## Error Handling + +{Common errors and how to handle them} + +## Examples + +### Example 1: {Use Case} + +**Input**: +- {param}: {value} + +**Expected Output**: +{What the user should see} + +## Notes + +{Additional tips or context} +``` + +### Step 6: Generate Helper Scripts + +For each identified script opportunity, create a Python script with: + +**Script Template**: +```python +#!/usr/bin/env python3 +""" +{Script description} + +Usage: + python3 {script_name}.py [arguments] + +Arguments: + {arg1}: {description} + {arg2}: {description} +""" + +import sys +import json +import argparse +from pathlib import Path + + +def main(): + """Main function implementing the script logic.""" + parser = argparse.ArgumentParser(description="{Script description}") + parser.add_argument("{arg1}", help="{description}") + parser.add_argument("{arg2}", help="{description}", nargs="?") + + args = parser.parse_args() + + # Implementation based on workflow pattern + try: + # Core logic here + result = process_data(args.{arg1}) + print(json.dumps(result, indent=2)) + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def process_data(input_data): + """Process the input data according to the workflow pattern.""" + # Implementation extracted from session workflow + pass + + +if __name__ == "__main__": + main() +``` + +**Script Guidelines**: +- Include proper error handling +- Accept parameters via command-line arguments +- Output results in a structured format (JSON when appropriate) +- Include usage documentation in docstring +- Make scripts executable (`chmod +x`) + +### Step 7: Prompt for Skill Name + +Ask the user: **"What would you like to name this skill?"** + +**Naming Guidelines**: +- Use lowercase letters +- Separate words with hyphens (kebab-case) +- Be descriptive but concise +- Examples: `read-file-with-permissions`, `deploy-to-staging`, `analyze-logs` + +**Suggest a name** based on the workflow if the user is unsure: +- Extract key actions and objects from the workflow +- Combine into a descriptive name +- Example: "Read file → Check permissions → Search" → `read-file-with-permission-check` + +### Step 8: Check for Existing Skill + +Before saving, check if a skill with this name already exists: + +**Action**: Check if `~/.claude/skills/{skill-name}/SKILL.md` exists + +**If exists**: +- Inform the user +- Ask: "A skill with this name already exists. Would you like to:" + - Overwrite the existing skill + - Choose a different name + - Cancel + +### Step 9: Save the Skill + +**Action**: Create the skill directory structure and save all files + +1. Create directory: `~/.claude/skills/{skill-name}/` +2. Write SKILL.md to: `~/.claude/skills/{skill-name}/SKILL.md` +3. If scripts were generated: + - Create directory: `~/.claude/skills/{skill-name}/scripts/` + - Write each script to: `~/.claude/skills/{skill-name}/scripts/{script_name}.py` + - Make scripts executable: `chmod +x ~/.claude/skills/{skill-name}/scripts/*.py` +4. Ensure proper permissions (readable by user) + +**Directory Structure**: +``` +~/.claude/skills/{skill-name}/ +├── SKILL.md +└── scripts/ (if applicable) + ├── script1.py + └── script2.py +``` + +**Note**: The skill is saved to the user's home directory (`~/.claude/skills/`) making it available across all projects. + +### Step 10: Provide Summary + +Present a clear summary to the user: + +``` +✅ Skill saved successfully! + +**Skill Name**: {skill-name} +**Location**: ~/.claude/skills/{skill-name}/ + +**Files Created**: +- SKILL.md (workflow documentation) +{if scripts} +- scripts/{script1}.py (helper script for {purpose}) +- scripts/{script2}.py (helper script for {purpose}) +{endif} + +**Summary**: {Brief description of what the skill does} + +**Workflow Captured**: +1. {Step 1 summary} +2. {Step 2 summary} +3. {Step 3 summary} +... + +**Parameters**: +- **{param1}**: {description} +- **{param2}**: {description} + +**Helper Scripts**: +{if scripts} +- **{script1}.py**: {what it does} +- **{script2}.py**: {what it does} +{endif} + +**To use this skill**: Simply reference it by name in future sessions: "{skill-name}" +``` + +## Error Handling + +**Session Too Short**: +- If the session has fewer than 3 meaningful exchanges, inform the user +- Suggest completing more of the task before saving as a skill + +**No Clear Workflow**: +- If the conversation doesn't show a clear workflow pattern, ask the user to clarify +- Request: "Could you describe the key steps you want to capture?" + +**Skill Name Conflicts**: +- If the name already exists, provide options (overwrite, rename, cancel) +- Never silently overwrite without user confirmation + +**Invalid Skill Name**: +- If the name contains invalid characters (spaces, special chars), suggest corrections +- Example: "My Skill!" → "my-skill" + +**Script Generation Errors**: +- If script generation fails, save the SKILL.md anyway +- Inform user they can add scripts manually later +- Provide guidance on what the script should do + +## Examples + +### Example 1: Saving a File Reading Workflow (with script) + +**Session Context**: +``` +User: "Read the states.txt file and parse it into a JSON array" +Assistant: [Reads file, parses lines, converts to JSON, outputs result] +User: "Great! Save this as a skill" +``` + +**Generated Skill Name**: `read-and-parse-file` + +**Parameters Identified**: +- `filename`: The file to read +- `output_format`: Format for output (json, csv, etc.) + +**Workflow Captured**: +1. Read file from workspace +2. Parse file contents line by line +3. Convert to specified format +4. Output formatted result + +**Scripts Generated**: +- `parse_file.py`: Reads a file and converts it to JSON format + +**Files Created**: +``` +~/.claude/skills/read-and-parse-file/ +├── SKILL.md +└── scripts/ + └── parse_file.py +``` + +### Example 2: Saving a Deployment Workflow (with multiple scripts) + +**Session Context**: +``` +User: "Deploy the app to staging" +Assistant: [Runs tests, builds app, uploads to server, restarts service] +User: "Perfect! Save this workflow" +``` + +**Generated Skill Name**: `deploy-to-staging` + +**Parameters Identified**: +- `app_name`: Name of the application +- `server_address`: Staging server address + +**Workflow Captured**: +1. Run test suite +2. Build application +3. Upload to staging server +4. Restart service +5. Verify deployment + +**Scripts Generated**: +- `run_tests.py`: Execute test suite and report results +- `deploy.py`: Handle upload and service restart + +**Files Created**: +``` +~/.claude/skills/deploy-to-staging/ +├── SKILL.md +└── scripts/ + ├── run_tests.py + └── deploy.py +``` + +### Example 3: Simple Workflow (no scripts needed) + +**Session Context**: +``` +User: "List all Python files in the project" +Assistant: [Uses glob tool to find *.py files, displays results] +User: "Save this" +``` + +**Generated Skill Name**: `list-python-files` + +**Workflow Captured**: +1. Use glob tool with pattern "**/*.py" +2. Format and display results + +**Scripts Generated**: None (simple tool call, no script needed) + +**Files Created**: +``` +~/.claude/skills/list-python-files/ +└── SKILL.md +``` + +## Notes + +- **Conservative Parameterization**: Only obvious session-specific values are parameterized. You can manually edit the generated skill later for more customization. +- **Cross-Project Availability**: Skills are saved to `~/.claude/skills/` making them available in all your projects. +- **Manual Editing**: After generation, you can manually edit the SKILL.md file and scripts to refine the workflow, add more examples, or adjust parameters. +- **Script Reusability**: Generated scripts can be used standalone or called from other scripts. +- **Skill Composition**: Generated skills can reference other skills, creating powerful workflow chains. +- **Version Control**: Consider adding your `~/.claude/skills/` directory to version control to track skill evolution. + +## Tips for Better Skills + +1. **Complete the task first**: Make sure your workflow is successful before saving it as a skill +2. **Clear session**: The clearer your session workflow, the better the generated skill and scripts +3. **Descriptive names**: Choose skill names that clearly indicate what they do +4. **Test scripts**: After generation, test the helper scripts to ensure they work correctly +5. **Add context**: After generation, consider adding more examples or notes to the skill +6. **Refine scripts**: Review generated scripts and add error handling or features as needed +7. **Document parameters**: Ensure all script parameters are well-documented in both SKILL.md and script docstrings diff --git a/tests/data/trajectory.json b/tests/data/trajectory.json index fa344062..6e08e4b2 100644 --- a/tests/data/trajectory.json +++ b/tests/data/trajectory.json @@ -5,7 +5,7 @@ }, { "role": "assistant", - "content": "[Thinking] The user wants me to read a file called \"states.txt\" to see what states they have teammates in. They specifically asked me to use the filesystem MCP tool.\n\nLet me use the MCP filesystem tool to read the file. I should use `mcp__filesystem__read_text_file` to read the states.txt file.\n\nFirst, I need to determine the path. Since they just mentioned \"states.txt\", I should look for it in the current working directory which is `/Users/vinod/data/digitallabor/src/agents/cuga-agent`.\n\nLet me read the file using the MCP filesystem tool." + "content": "[Thinking] The user wants me to read a file called \"states.txt\" to see what states they have teammates in. They specifically asked me to use the filesystem MCP tool.\n\nLet me use the MCP filesystem tool to read the file. I should use `mcp__filesystem__read_text_file` to read the states.txt file.\n\nFirst, I need to determine the path. Since they just mentioned \"states.txt\", I should look for it in the current working directory which is `/home/user/workspace/my-agent`.\n\nLet me read the file using the MCP filesystem tool." }, { "role": "assistant", @@ -19,7 +19,7 @@ "id": "toolu_bdrk_012ZqXZPtv9YYgTewFGcEMVY", "function": { "name": "mcp__filesystem__read_text_file", - "arguments": "{\"path\": \"/Users/vinod/data/digitallabor/src/agents/cuga-agent/states.txt\"}" + "arguments": "{\"path\": \"/home/user/workspace/my-agent/states.txt\"}" } } ] @@ -30,7 +30,7 @@ { "type": "function_response", "id": "toolu_bdrk_012ZqXZPtv9YYgTewFGcEMVY", - "content": "Error executing tool read_text_file: Access denied: /Users/vinod/data/digitallabor/src/agents/cuga-agent/states.txt is outside allowed directories", + "content": "Error executing tool read_text_file: Access denied: /home/user/workspace/my-agent/states.txt is outside allowed directories", "is_error": true } ] @@ -62,14 +62,14 @@ { "type": "function_response", "id": "toolu_bdrk_015PGARmfmBTw2bgyHZfWNHc", - "content": "{\"result\":\"Allowed directories:\\n/Users/vinod/data/digitallabor/src/agents/cuga-agent/cuga_workspace\"}", + "content": "{\"result\":\"Allowed directories:\\n/home/user/workspace/my-agent/cuga_workspace\"}", "is_error": false } ] }, { "role": "assistant", - "content": "[Thinking] The MCP filesystem tool only has access to `/Users/vinod/data/digitallabor/src/agents/cuga-agent/cuga_workspace`, but the states.txt file appears to be in the parent directory `/Users/vinod/data/digitallabor/src/agents/cuga-agent/`.\n\nLet me try to find the states.txt file in the allowed directory or check if it exists there:" + "content": "[Thinking] The MCP filesystem tool only has access to `/home/user/workspace/my-agent/cuga_workspace`, but the states.txt file appears to be in the parent directory `/home/user/workspace/my-agent/`.\n\nLet me try to find the states.txt file in the allowed directory or check if it exists there:" }, { "role": "assistant", @@ -83,7 +83,7 @@ "id": "toolu_bdrk_01MoL1wd2WMsrxZcPST316Bj", "function": { "name": "mcp__filesystem__search_files", - "arguments": "{\"path\": \"/Users/vinod/data/digitallabor/src/agents/cuga-agent/cuga_workspace\", \"pattern\": \"states.txt\"}" + "arguments": "{\"path\": \"/home/user/workspace/my-agent/cuga_workspace\", \"pattern\": \"states.txt\"}" } } ] @@ -94,7 +94,7 @@ { "type": "function_response", "id": "toolu_bdrk_01MoL1wd2WMsrxZcPST316Bj", - "content": "{\"result\":\"/Users/vinod/data/digitallabor/src/agents/cuga-agent/cuga_workspace/states.txt\"}", + "content": "{\"result\":\"/home/user/workspace/my-agent/cuga_workspace/states.txt\"}", "is_error": false } ] @@ -115,7 +115,7 @@ "id": "toolu_bdrk_01XQyfKBJqFeZsFyN4AWhHjd", "function": { "name": "mcp__filesystem__read_text_file", - "arguments": "{\"path\": \"/Users/vinod/data/digitallabor/src/agents/cuga-agent/cuga_workspace/states.txt\"}" + "arguments": "{\"path\": \"/home/user/workspace/my-agent/cuga_workspace/states.txt\"}" } } ]