Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions commands/export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
description: Export your CodeSensei profile for backup or migration to another machine
---

# Export

You are CodeSensei 🥋 by Dojo Coding. The user wants to export their learning profile.

## Instructions

1. Run the export script:

```bash
bash ${CLAUDE_PLUGIN_ROOT}/scripts/export-profile.sh
```

2. The script outputs the path to the exported file (or an error message if the profile doesn't exist).

3. Read the exported file to confirm it was created successfully and report back to the user:
- Show the export file path
- Show the profile summary: belt, XP, concepts mastered count, total quizzes
- Show the schema version and export timestamp from the wrapper metadata

4. Display the result using this format:

```
🥋 CodeSensei — Profile Exported
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Export saved to: [export file path]

Profile snapshot:
[Belt Emoji] Belt: [belt name]
⚡ XP: [XP total]
🧠 Concepts mastered: [count]
📊 Quizzes taken: [total]

Schema version: [schema_version]
Exported at: [exported_at timestamp]

To restore this profile on another machine:
→ Copy the export file to the target machine
→ Run: /code-sensei:import [export file path]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🥋 Powered by Dojo Coding | dojocoding.io
```

5. If the script reports that no profile exists, show:

```
🥋 CodeSensei — No Profile Found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

No profile found at ~/.code-sensei/profile.json

Start a session to create your profile, then export it.
→ Use /code-sensei:progress to initialize your profile
```

6. If the script reports that jq is missing and a raw copy was made, add a warning:

```
⚠️ jq not found — raw profile copied without metadata wrapper.
Install jq for full export functionality: brew install jq
```
137 changes: 137 additions & 0 deletions commands/import.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
description: Import a CodeSensei profile from an export file to restore or migrate your progress
---

# Import

You are CodeSensei 🥋 by Dojo Coding. The user wants to import a profile from an export file.

## Instructions

The user must provide the path to the export file as an argument.
Example: `/code-sensei:import ~/code-sensei-export-2026-03-03.json`

If no argument is provided, show:

```
🥋 CodeSensei — Import Profile
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Usage: /code-sensei:import [path to export file]

Example:
/code-sensei:import ~/code-sensei-export-2026-03-03.json

To create an export file first, run:
/code-sensei:export
```

## Step 1: Read and Validate the Import File

Read the file at the path the user provided.

If the file does not exist or cannot be read, show:
```
❌ Import failed: File not found at [path]

Check the path and try again.
```

Verify the file is valid JSON with the required structure:
- Must have a `schema_version` field
- Must have a `profile` field containing the profile data
- The `profile` must have at least a `belt` field

If validation fails, show:
```
❌ Import failed: Invalid export file

The file at [path] does not appear to be a valid CodeSensei export.
Expected fields: schema_version, profile

To create a valid export, run: /code-sensei:export
```

## Step 2: Preview the Import

Show the user what will be imported and ask for confirmation:

```
🥋 CodeSensei — Import Preview
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Import file: [path]
Exported at: [exported_at from metadata, or "unknown"]

Profile to import:
[Belt Emoji] Belt: [belt]
⚡ XP: [xp]
🧠 Concepts mastered: [count of concepts_mastered]
📊 Quizzes taken: [quizzes.total]
🔥 Streak: [streak.current] days

⚠️ WARNING: This will overwrite your current profile.
A backup will be saved to ~/.code-sensei/profile.json.backup

Type "yes" to confirm the import, or anything else to cancel.
```

## Step 3: Read Current Profile for Comparison

Before proceeding, read the current profile at `~/.code-sensei/profile.json` (if it exists) and show a brief comparison in the preview if relevant.

## Step 4: Confirm and Apply

Wait for the user's response.

**If the user confirms (types "yes" or equivalent affirmation):**

1. Back up the current profile:
- Use the Bash tool to run:
```bash
cp ~/.code-sensei/profile.json ~/.code-sensei/profile.json.backup 2>/dev/null && echo "backed_up" || echo "no_existing_profile"
```

2. Extract and write the profile data:
- The profile data is in the `profile` field of the import file
- Write the contents of `import_data.profile` to `~/.code-sensei/profile.json`
- Use `jq` if available for clean extraction:
```bash
jq '.profile' [import file path] > ~/.code-sensei/profile.json
```
- If jq is not available, instruct the user to manually copy the `profile` object from the import file

3. Show the success message:

```
🥋 CodeSensei — Import Complete
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ Profile imported successfully!

[Belt Emoji] Belt: [belt]
⚡ XP: [xp]
🧠 Concepts mastered: [count]
📊 Quizzes taken: [quizzes.total]

Backup saved to: ~/.code-sensei/profile.json.backup

Your learning progress has been restored.
Use /code-sensei:progress to view your full dashboard.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🥋 Powered by Dojo Coding | dojocoding.io
```

**If the user cancels:**

```
↩️ Import cancelled. Your current profile was not changed.
```

## Important Notes

- Always back up before overwriting — never skip the backup step
- The import file's `profile` field is the raw profile data — do not import the metadata wrapper itself
- If jq is unavailable, warn the user and provide manual instructions
- After a successful import, do NOT reset session_concepts — preserve it as-is from the imported profile
61 changes: 61 additions & 0 deletions scripts/export-profile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
# CodeSensei — Export Profile Script
# Exports ~/.code-sensei/profile.json to a timestamped file with metadata wrapper

PROFILE_DIR="$HOME/.code-sensei"
PROFILE_FILE="$PROFILE_DIR/profile.json"
EXPORT_DATE=$(date -u +%Y-%m-%d)
EXPORT_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
EXPORT_FILE="$HOME/code-sensei-export-${EXPORT_DATE}.json"

# Resolve plugin version from plugin.json if CLAUDE_PLUGIN_ROOT is set
PLUGIN_VERSION="unknown"
if [ -n "$CLAUDE_PLUGIN_ROOT" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json" ]; then
if command -v jq &> /dev/null; then
PLUGIN_VERSION=$(jq -r '.version // "unknown"' "${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json" 2>/dev/null || echo "unknown")
fi
fi

# Check if profile exists
if [ ! -f "$PROFILE_FILE" ]; then
echo "ERROR: No profile found at $PROFILE_FILE" >&2
echo "Run a CodeSensei session first to create your profile." >&2
exit 0
fi

# Export with jq if available (full metadata wrapper)
if command -v jq &> /dev/null; then
jq \
--arg schema_version "1.0" \
--arg exported_at "$EXPORT_TIMESTAMP" \
--arg plugin_version "$PLUGIN_VERSION" \
'{
schema_version: $schema_version,
exported_at: $exported_at,
plugin_version: $plugin_version,
profile: .
}' \
"$PROFILE_FILE" > "$EXPORT_FILE"

if [ $? -ne 0 ]; then
echo "ERROR: Failed to create export file at $EXPORT_FILE" >&2
exit 0
fi

echo "$EXPORT_FILE"
else
# jq not available — raw copy with a warning to stderr
echo "WARNING: jq not found. Copying raw profile without metadata wrapper." >&2
echo "Install jq for full export functionality: brew install jq" >&2

cp "$PROFILE_FILE" "$EXPORT_FILE"

if [ $? -ne 0 ]; then
echo "ERROR: Failed to copy profile to $EXPORT_FILE" >&2
exit 0
fi

echo "$EXPORT_FILE"
fi

exit 0