Skip to content

Commit f72705b

Browse files
committed
fix: make profile exports portable
1 parent c00e781 commit f72705b

3 files changed

Lines changed: 38 additions & 21 deletions

File tree

commands/export.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ Start a session to create your profile, then export it.
5858
→ Use /code-sensei:progress to initialize your profile
5959
```
6060

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

6363
```
64-
⚠️ jq not found — raw profile copied without metadata wrapper.
65-
Install jq for full export functionality: brew install jq
64+
⚠️ jq not found — export created without jq validation/pretty formatting.
65+
The file is still importable. Install jq for full export functionality: brew install jq
6666
```

commands/import.md

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,16 @@ If the file does not exist or cannot be read, show:
3737
Check the path and try again.
3838
```
3939

40-
Verify the file is valid JSON with the required structure:
41-
- Must have a `schema_version` field
42-
- Must have a `profile` field containing the profile data
43-
- The `profile` must have at least a `belt` field
40+
Verify the file is valid JSON in one of these formats:
41+
- Preferred export format: must have a `schema_version` field and a `profile` field containing the profile data
42+
- Legacy/raw export format: may be the raw profile JSON itself, as long as it has at least a `belt` field
4443

4544
If validation fails, show:
4645
```
4746
❌ Import failed: Invalid export file
4847
4948
The file at [path] does not appear to be a valid CodeSensei export.
50-
Expected fields: schema_version, profile
49+
Expected either a wrapped export (`schema_version` + `profile`) or a raw profile JSON with `belt`.
5150
5251
To create a valid export, run: /code-sensei:export
5352
```
@@ -61,7 +60,7 @@ Show the user what will be imported and ask for confirmation:
6160
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
6261
6362
Import file: [path]
64-
Exported at: [exported_at from metadata, or "unknown"]
63+
Exported at: [exported_at from metadata, or "unknown" for legacy/raw exports]
6564
6665
Profile to import:
6766
[Belt Emoji] Belt: [belt]
@@ -92,16 +91,26 @@ Wait for the user's response.
9291
cp ~/.code-sensei/profile.json ~/.code-sensei/profile.json.backup 2>/dev/null && echo "backed_up" || echo "no_existing_profile"
9392
```
9493

95-
2. Extract and write the profile data:
96-
- The profile data is in the `profile` field of the import file
97-
- Write the contents of `import_data.profile` to `~/.code-sensei/profile.json`
94+
2. Create the target directory if needed:
95+
- Use the Bash tool to run:
96+
```bash
97+
mkdir -p ~/.code-sensei
98+
```
99+
100+
3. Extract and write the profile data:
101+
- If the import file has a `profile` field, write `import_data.profile` to `~/.code-sensei/profile.json`
102+
- If it is a legacy/raw export, write the full file contents as-is to `~/.code-sensei/profile.json`
98103
- Use `jq` if available for clean extraction:
99104
```bash
100-
jq '.profile' [import file path] > ~/.code-sensei/profile.json
105+
if jq -e '.profile' [import file path] > /dev/null 2>&1; then
106+
jq '.profile' [import file path] > ~/.code-sensei/profile.json
107+
else
108+
cp [import file path] ~/.code-sensei/profile.json
109+
fi
101110
```
102-
- If jq is not available, instruct the user to manually copy the `profile` object from the import file
111+
- If jq is not available, instruct the user to manually copy the `profile` object from the import file, or the full file for legacy/raw exports
103112

104-
3. Show the success message:
113+
4. Show the success message:
105114

106115
```
107116
🥋 CodeSensei — Import Complete
@@ -132,6 +141,6 @@ Use /code-sensei:progress to view your full dashboard.
132141
## Important Notes
133142

134143
- Always back up before overwriting — never skip the backup step
135-
- The import file's `profile` field is the raw profile data — do not import the metadata wrapper itself
144+
- The preferred import path reads the `profile` field from wrapped exports; legacy/raw exports can be copied directly
136145
- If jq is unavailable, warn the user and provide manual instructions
137146
- After a successful import, do NOT reset session_concepts — preserve it as-is from the imported profile

scripts/export-profile.sh

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

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

1111
# Resolve plugin version from plugin.json if CLAUDE_PLUGIN_ROOT is set
1212
PLUGIN_VERSION="unknown"
@@ -44,11 +44,19 @@ if command -v jq &> /dev/null; then
4444

4545
echo "$EXPORT_FILE"
4646
else
47-
# jq not available — raw copy with a warning to stderr
48-
echo "WARNING: jq not found. Copying raw profile without metadata wrapper." >&2
47+
# jq not available — still create an importable wrapper without validation/pretty-printing
48+
echo "WARNING: jq not found. Creating export without jq validation/pretty formatting." >&2
4949
echo "Install jq for full export functionality: brew install jq" >&2
5050

51-
cp "$PROFILE_FILE" "$EXPORT_FILE"
51+
{
52+
printf '{\n'
53+
printf ' "schema_version": "1.0",\n'
54+
printf ' "exported_at": "%s",\n' "$EXPORT_TIMESTAMP"
55+
printf ' "plugin_version": "%s",\n' "$PLUGIN_VERSION"
56+
printf ' "profile": '
57+
cat "$PROFILE_FILE"
58+
printf '\n}\n'
59+
} > "$EXPORT_FILE"
5260

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

0 commit comments

Comments
 (0)