replit-tools 1.0.2 → 1.0.4

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.
Files changed (3) hide show
  1. package/README.md +148 -46
  2. package/index.js +100 -41
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,46 +1,52 @@
1
- # replit-claude-persist
1
+ # DATA Tools
2
2
 
3
- **Persist Claude Code sessions, authentication, and history across Replit container restarts.**
3
+ **One command to set up Claude Code and Codex CLI on Replit with full persistence.**
4
4
 
5
- When Replit containers restart, everything outside `/home/runner/workspace/` is wiped - including your Claude conversations, auth tokens, and installed binaries. This tool fixes that.
5
+ When Replit containers restart, everything outside `/home/runner/workspace/` is wiped - including installed CLIs, conversations, auth tokens, and command history. DATA Tools fixes all of that.
6
6
 
7
- ## Features
7
+ ## Quick Start
8
8
 
9
- - **Session Persistence** - Conversations survive container restarts
10
- - **Interactive Session Picker** - Choose which session to resume on shell start
11
- - **Multi-Terminal Support** - Each terminal tracks its own session
12
- - **Auth Persistence** - Keep your Claude authentication working
13
- - **Binary Caching** - Claude binary persists (faster startup)
14
- - **Bash History** - Command history survives restarts too
9
+ ```bash
10
+ npx replit-tools
11
+ ```
15
12
 
16
- ## Installation
13
+ That's it. The installer will:
17
14
 
18
- ### Option 1: npx (easiest)
15
+ 1. **Install Claude Code** (if not already installed)
16
+ 2. **Install OpenAI Codex CLI** (if not already installed)
17
+ 3. **Detect existing config** and preserve your data
18
+ 4. **Set up persistence** so everything survives restarts
19
+ 5. **Launch the session picker** so you can start working immediately
19
20
 
20
- ```bash
21
- npx replit-claude-persist
22
- ```
21
+ ## What Gets Installed
23
22
 
24
- ### Option 2: curl
23
+ | Tool | Source | Purpose |
24
+ |------|--------|---------|
25
+ | **Claude Code** | `curl https://claude.ai/install.sh` | Anthropic's CLI for Claude |
26
+ | **Codex CLI** | `npm i -g @openai/codex` | OpenAI's coding assistant |
25
27
 
26
- ```bash
27
- curl -fsSL https://raw.githubusercontent.com/stevemoraco/DATAtools/main/install.sh | bash
28
- ```
28
+ Both are installed only if not already present. Existing installations are preserved.
29
29
 
30
- ### Option 3: Manual
30
+ ## What Gets Persisted
31
31
 
32
- ```bash
33
- npm install -g replit-claude-persist
34
- replit-claude-persist
35
- ```
32
+ | Data | Location | Survives Restart? |
33
+ |------|----------|-------------------|
34
+ | Claude conversations | `.claude-persistent/` | Yes |
35
+ | Claude credentials | `.claude-persistent/` | Yes |
36
+ | Claude binary | `.local/share/claude/versions/` | Yes |
37
+ | Codex data | `.codex-persistent/` | Yes |
38
+ | Bash history | `.persistent-home/` | Yes |
39
+ | Per-terminal sessions | `.claude-sessions/` | Yes |
36
40
 
37
- ## What You'll See
41
+ ## The Session Picker
38
42
 
39
- After installation, opening a new shell shows:
43
+ After installation (and on every new shell), you'll see:
40
44
 
41
45
  ```
46
+ ✅ Claude Code already installed (1.0.17)
47
+ ✅ Codex CLI already installed
48
+
42
49
  ✅ Claude authentication: valid (23h remaining)
43
- ✅ Claude Code ready: 2.0.71 (Claude Code)
44
50
 
45
51
  ╭─────────────────────────────────────────────────────────╮
46
52
  │ Claude Session Manager │
@@ -56,7 +62,9 @@ After installation, opening a new shell shows:
56
62
  Choice [c/r/n/s]: _
57
63
  ```
58
64
 
59
- Press `r` to see detailed session info:
65
+ ### Session Details
66
+
67
+ Press `r` to see full session metadata:
60
68
 
61
69
  ```
62
70
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -69,30 +77,99 @@ Press `r` to see detailed session info:
69
77
  Latest: "Thanks, that worked!"
70
78
  ```
71
79
 
80
+ Each session shows:
81
+ - Full UUID
82
+ - Message count and file size
83
+ - Time since last activity
84
+ - Start and last activity timestamps
85
+ - First and latest prompts (truncated)
86
+
87
+ ## Multi-Terminal Support
88
+
89
+ Each terminal tracks its own session independently:
90
+
91
+ ```
92
+ Terminal pts/0 → Session abc123... (your migration work)
93
+ Terminal pts/1 → Session def456... (your docs work)
94
+ Terminal pts/2 → Session ghi789... (your debugging)
95
+ ```
96
+
97
+ Press `c` to continue YOUR terminal's last session. Other terminals are unaffected.
98
+
72
99
  ## How It Works
73
100
 
74
- The tool creates symlinks from ephemeral locations to persistent workspace storage:
101
+ The installer creates symlinks from ephemeral locations to persistent workspace storage:
75
102
 
76
103
  ```
77
- ~/.claude → /workspace/.claude-persistent/
78
- ~/.codex → /workspace/.codex-persistent/
79
- ~/.local/bin/ → /workspace/.local/share/claude/versions/
104
+ ~/.claude → /workspace/.claude-persistent/
105
+ ~/.codex → /workspace/.codex-persistent/
106
+ ~/.local/share/claude → /workspace/.local/share/claude/
107
+ ~/.local/bin/claude → /workspace/.local/share/claude/versions/X.X.X
80
108
  ```
81
109
 
82
- On every shell start, `.config/bashrc` ensures symlinks exist and shows the session picker.
110
+ Three layers ensure setup runs on every restart:
111
+ 1. `.replit` onBoot hook (runs at container boot)
112
+ 2. `.config/bashrc` (runs on every shell start)
113
+ 3. Scripts in `workspace/scripts/` (called by above)
114
+
115
+ ## Smart Detection
116
+
117
+ The installer checks for:
118
+
119
+ - **`CLAUDE_CONFIG_DIR`** - Respects custom Claude config directory if set in Replit Secrets
120
+ - **Existing persistent config** - Uses your existing `.claude-persistent/` if present
121
+ - **Replit Secrets** - Detects `ANTHROPIC_API_KEY` and `OPENAI_API_KEY`
122
+ - **Existing installations** - Won't reinstall Claude or Codex if already present
123
+ - **Existing data in ~/.claude** - Moves it to persistent storage instead of overwriting
124
+
125
+ ### Supported Environment Variables
126
+
127
+ | Variable | Purpose |
128
+ |----------|---------|
129
+ | `CLAUDE_CONFIG_DIR` | Custom directory for Claude config/data (recommended) |
130
+ | `CLAUDE_WORKSPACE_DIR` | Alternative name for config directory |
131
+ | `CLAUDE_DATA_DIR` | Alternative name for config directory |
132
+ | `CLAUDE_HOME` | Alternative name for config directory |
133
+ | `ANTHROPIC_API_KEY` | Claude API authentication |
134
+ | `OPENAI_API_KEY` | Codex API authentication |
135
+
136
+ If you set `CLAUDE_CONFIG_DIR` in your Replit Secrets to a path inside `/home/runner/workspace/`, DATA Tools will use that directory for persistence instead of the default `.claude-persistent/`.
137
+
138
+ ## Installation Options
139
+
140
+ ### Option 1: npx (recommended)
141
+
142
+ ```bash
143
+ npx replit-tools
144
+ ```
145
+
146
+ ### Option 2: curl
147
+
148
+ ```bash
149
+ curl -fsSL https://raw.githubusercontent.com/stevemoraco/DATAtools/main/install.sh | bash
150
+ ```
151
+
152
+ ### Option 3: Global install
153
+
154
+ ```bash
155
+ npm install -g replit-tools
156
+ replit-tools
157
+ ```
83
158
 
84
159
  ## Commands
85
160
 
161
+ After installation, these aliases are available:
162
+
86
163
  | Command | Description |
87
164
  |---------|-------------|
88
- | `cr` | Continue last session |
89
- | `claude-menu` | Show session picker again |
90
- | `claude-new` | Start fresh session |
91
- | `claude-pick` | Claude's built-in picker |
165
+ | `cr` | Continue last Claude session |
166
+ | `claude-resume` | Same as `cr` |
167
+ | `claude-pick` | Claude's built-in session picker |
168
+ | `claude-menu` | Show the session manager menu again |
92
169
 
93
170
  ## Configuration
94
171
 
95
- ### Disable the menu
172
+ ### Disable the session picker menu
96
173
 
97
174
  ```bash
98
175
  export CLAUDE_NO_PROMPT=true
@@ -100,32 +177,39 @@ export CLAUDE_NO_PROMPT=true
100
177
 
101
178
  Add to `.config/bashrc` to make permanent.
102
179
 
103
- ### Fix auth permanently
180
+ ### Fix authentication permanently
104
181
 
105
182
  ```bash
106
183
  claude setup-token
107
184
  ```
108
185
 
109
- Creates a long-lived token that doesn't expire.
186
+ Creates a long-lived API token that doesn't expire (OAuth tokens expire every ~24h).
110
187
 
111
188
  ## Files Created
112
189
 
113
190
  ```
114
191
  workspace/
115
- ├── .claude-persistent/ # Conversations, credentials
192
+ ├── .claude-persistent/ # Claude conversations & credentials
116
193
  ├── .codex-persistent/ # Codex CLI data
117
194
  ├── .claude-sessions/ # Per-terminal session tracking
118
195
  ├── .local/share/claude/ # Claude binary versions
119
196
  ├── .persistent-home/ # Bash history
120
197
  ├── .config/bashrc # Shell startup config
121
- └── scripts/
122
- ├── setup-claude-code.sh
123
- └── claude-session-manager.sh
198
+ ├── scripts/
199
+ ├── setup-claude-code.sh
200
+ └── claude-session-manager.sh
201
+ └── .gitignore # Updated to ignore credential dirs
124
202
  ```
125
203
 
126
204
  ## Troubleshooting
127
205
 
128
- ### Menu not appearing
206
+ ### Claude or Codex not found after restart
207
+
208
+ ```bash
209
+ source /home/runner/workspace/scripts/setup-claude-code.sh
210
+ ```
211
+
212
+ ### Session picker not appearing
129
213
 
130
214
  ```bash
131
215
  source /home/runner/workspace/.config/bashrc
@@ -142,9 +226,27 @@ claude setup-token
142
226
  ### Symlinks broken
143
227
 
144
228
  ```bash
145
- source /home/runner/workspace/scripts/setup-claude-code.sh
229
+ npx replit-tools
146
230
  ```
147
231
 
232
+ Running the installer again is safe - it preserves existing data.
233
+
234
+ ## Security
235
+
236
+ The installer adds these to `.gitignore`:
237
+ - `.claude-persistent/` (contains credentials)
238
+ - `.codex-persistent/` (contains credentials)
239
+
240
+ Your API keys and conversation history won't be committed to git.
241
+
242
+ ## Why "DATA Tools"?
243
+
244
+ **D**eveloper **A**ssistant **T**ool **A**utomation - everything you need to run AI coding assistants on Replit, persisted and ready to go.
245
+
246
+ ## Repository
247
+
248
+ GitHub: [stevemoraco/DATAtools](https://github.com/stevemoraco/DATAtools)
249
+
148
250
  ## License
149
251
 
150
252
  MIT
package/index.js CHANGED
@@ -17,7 +17,7 @@ if (!fs.existsSync(WORKSPACE)) {
17
17
 
18
18
  console.log('');
19
19
  console.log('╭─────────────────────────────────────────────────────────╮');
20
- console.log('│ Replit Tools - Claude & Codex Persistence │');
20
+ console.log('│ DATA Tools - Claude & Codex Persistence │');
21
21
  console.log('╰─────────────────────────────────────────────────────────╯');
22
22
  console.log('');
23
23
 
@@ -31,33 +31,66 @@ function commandExists(cmd) {
31
31
  }
32
32
  }
33
33
 
34
- // Helper to check for Replit secret
35
- function hasReplitSecret(name) {
36
- return process.env[name] !== undefined;
34
+ // Helper to get Replit secret value
35
+ function getReplitSecret(name) {
36
+ return process.env[name] || null;
37
+ }
38
+
39
+ // Check for CLAUDE_CONFIG_DIR or similar env vars that specify custom Claude location
40
+ const claudeConfigEnvVars = [
41
+ 'CLAUDE_CONFIG_DIR',
42
+ 'CLAUDE_WORKSPACE_DIR',
43
+ 'CLAUDE_DATA_DIR',
44
+ 'CLAUDE_HOME'
45
+ ];
46
+
47
+ let customClaudeDir = null;
48
+ for (const envVar of claudeConfigEnvVars) {
49
+ const value = getReplitSecret(envVar);
50
+ if (value) {
51
+ customClaudeDir = value;
52
+ console.log(`✅ Found ${envVar} = ${value}`);
53
+ break;
54
+ }
55
+ }
56
+
57
+ // Determine Claude persistent directory
58
+ // Priority: 1) CLAUDE_CONFIG_DIR from env, 2) existing .claude-persistent, 3) default
59
+ let claudePersistentDir = path.join(WORKSPACE, '.claude-persistent');
60
+
61
+ if (customClaudeDir) {
62
+ // User has specified a custom directory via env var
63
+ if (customClaudeDir.startsWith(WORKSPACE)) {
64
+ // It's already in workspace - use it directly
65
+ claudePersistentDir = customClaudeDir;
66
+ console.log(` Using custom Claude directory: ${claudePersistentDir}`);
67
+ } else {
68
+ // It's outside workspace - we'll symlink to it but also ensure persistence
69
+ console.log(` Custom dir outside workspace - will set up persistence`);
70
+ }
37
71
  }
38
72
 
39
73
  // Check for existing persistent config
40
- const existingClaudeConfig = fs.existsSync(path.join(WORKSPACE, '.claude-persistent'));
74
+ const existingClaudeConfig = fs.existsSync(claudePersistentDir);
41
75
  const existingCodexConfig = fs.existsSync(path.join(WORKSPACE, '.codex-persistent'));
42
76
 
43
77
  if (existingClaudeConfig) {
44
- console.log('✅ Found existing Claude config in workspace');
78
+ console.log(`✅ Found existing Claude config at ${claudePersistentDir}`);
45
79
  }
46
80
  if (existingCodexConfig) {
47
81
  console.log('✅ Found existing Codex config in workspace');
48
82
  }
49
83
 
50
- // Check for Replit secrets
51
- if (hasReplitSecret('ANTHROPIC_API_KEY')) {
84
+ // Check for API key secrets
85
+ if (getReplitSecret('ANTHROPIC_API_KEY')) {
52
86
  console.log('✅ Found ANTHROPIC_API_KEY in Replit secrets');
53
87
  }
54
- if (hasReplitSecret('OPENAI_API_KEY')) {
88
+ if (getReplitSecret('OPENAI_API_KEY')) {
55
89
  console.log('✅ Found OPENAI_API_KEY in Replit secrets');
56
90
  }
57
91
 
58
92
  // Create directories (preserving existing data)
59
93
  const dirs = [
60
- '.claude-persistent',
61
94
  '.codex-persistent',
62
95
  '.claude-sessions',
63
96
  '.local/share/claude/versions',
@@ -67,6 +100,14 @@ const dirs = [
67
100
  'logs'
68
101
  ];
69
102
 
103
+ // Add Claude persistent dir if it's relative to workspace
104
+ if (claudePersistentDir.startsWith(WORKSPACE)) {
105
+ const relativePath = claudePersistentDir.replace(WORKSPACE + '/', '');
106
+ if (!dirs.includes(relativePath)) {
107
+ dirs.unshift(relativePath);
108
+ }
109
+ }
110
+
70
111
  console.log('');
71
112
  console.log('📁 Creating directories...');
72
113
  dirs.forEach(dir => {
@@ -84,15 +125,19 @@ const claudeInstalled = commandExists('claude') ||
84
125
 
85
126
  let claudeVersions = [];
86
127
  try {
87
- claudeVersions = fs.readdirSync(path.join(WORKSPACE, '.local/share/claude/versions'));
128
+ claudeVersions = fs.readdirSync(path.join(WORKSPACE, '.local/share/claude/versions'))
129
+ .filter(f => !f.startsWith('.'));
88
130
  } catch {}
89
131
 
90
132
  if (!claudeInstalled || claudeVersions.length === 0) {
91
133
  console.log('📦 Installing Claude Code...');
92
134
  try {
135
+ // Set CLAUDE_CONFIG_DIR before install so it installs to the right place
136
+ const installEnv = { ...process.env, CLAUDE_CONFIG_DIR: claudePersistentDir };
93
137
  execSync('curl -fsSL https://claude.ai/install.sh | bash', {
94
138
  stdio: 'inherit',
95
- shell: '/bin/bash'
139
+ shell: '/bin/bash',
140
+ env: installEnv
96
141
  });
97
142
  console.log('✅ Claude Code installed');
98
143
  } catch (err) {
@@ -125,29 +170,30 @@ if (!codexInstalled) {
125
170
  console.log('');
126
171
  console.log('🔗 Setting up symlinks...');
127
172
 
128
- // Claude symlink
129
- const claudeTarget = path.join(WORKSPACE, '.claude-persistent');
173
+ // Claude symlink - only if we're using default location
130
174
  const claudeLink = path.join(HOME, '.claude');
131
- try {
132
- const stat = fs.lstatSync(claudeLink);
133
- if (stat.isSymbolicLink()) {
134
- const current = fs.readlinkSync(claudeLink);
135
- if (current !== claudeTarget) {
136
- fs.unlinkSync(claudeLink);
137
- fs.symlinkSync(claudeTarget, claudeLink);
175
+ if (!customClaudeDir || customClaudeDir.startsWith(WORKSPACE)) {
176
+ try {
177
+ const stat = fs.lstatSync(claudeLink);
178
+ if (stat.isSymbolicLink()) {
179
+ const current = fs.readlinkSync(claudeLink);
180
+ if (current !== claudePersistentDir) {
181
+ fs.unlinkSync(claudeLink);
182
+ fs.symlinkSync(claudePersistentDir, claudeLink);
183
+ }
184
+ } else if (stat.isDirectory()) {
185
+ // Move existing data to persistent location
186
+ console.log(' Moving existing ~/.claude data to persistent storage...');
187
+ execSync(`cp -rn ${claudeLink}/* ${claudePersistentDir}/ 2>/dev/null || true`, { shell: '/bin/bash' });
188
+ execSync(`rm -rf ${claudeLink}`, { shell: '/bin/bash' });
189
+ fs.symlinkSync(claudePersistentDir, claudeLink);
138
190
  }
139
- } else if (stat.isDirectory()) {
140
- // Move existing data to persistent location
141
- console.log(' Moving existing ~/.claude data to persistent storage...');
142
- execSync(`cp -rn ${claudeLink}/* ${claudeTarget}/ 2>/dev/null || true`, { shell: '/bin/bash' });
143
- execSync(`rm -rf ${claudeLink}`, { shell: '/bin/bash' });
144
- fs.symlinkSync(claudeTarget, claudeLink);
191
+ } catch {
192
+ // Doesn't exist, create it
193
+ fs.symlinkSync(claudePersistentDir, claudeLink);
145
194
  }
146
- } catch {
147
- // Doesn't exist, create it
148
- fs.symlinkSync(claudeTarget, claudeLink);
195
+ console.log(` ~/.claude ${claudePersistentDir.replace(WORKSPACE + '/', '')}/`);
149
196
  }
150
- console.log(' ~/.claude → .claude-persistent/');
151
197
 
152
198
  // Codex symlink
153
199
  const codexTarget = path.join(WORKSPACE, '.codex-persistent');
@@ -198,7 +244,9 @@ console.log(' ~/.local/share/claude → .local/share/claude/');
198
244
 
199
245
  // Link binary to latest version
200
246
  try {
201
- const versions = fs.readdirSync(path.join(WORKSPACE, '.local/share/claude/versions')).sort();
247
+ const versions = fs.readdirSync(path.join(WORKSPACE, '.local/share/claude/versions'))
248
+ .filter(f => !f.startsWith('.'))
249
+ .sort();
202
250
  if (versions.length > 0) {
203
251
  const latest = versions[versions.length - 1];
204
252
  const binaryPath = path.join(WORKSPACE, '.local/share/claude/versions', latest);
@@ -228,11 +276,15 @@ scripts.forEach(script => {
228
276
  }
229
277
  });
230
278
 
231
- // Create/update .config/bashrc
279
+ // Create/update .config/bashrc with CLAUDE_CONFIG_DIR export
232
280
  console.log('');
233
281
  console.log('📝 Creating .config/bashrc...');
234
282
  const bashrcContent = `#!/bin/bash
235
- # Replit Claude Persistence - Auto-generated bashrc
283
+ # DATA Tools - Replit Claude & Codex Persistence
284
+ # Auto-generated bashrc
285
+
286
+ # Claude Config Directory (tells Claude where to store data)
287
+ export CLAUDE_CONFIG_DIR="${claudePersistentDir}"
236
288
 
237
289
  # Claude Code Setup
238
290
  SETUP_SCRIPT="/home/runner/workspace/scripts/setup-claude-code.sh"
@@ -272,17 +324,17 @@ const onBootLine = 'onBoot = "source /home/runner/workspace/scripts/setup-claude
272
324
  if (fs.existsSync(replitPath)) {
273
325
  let content = fs.readFileSync(replitPath, 'utf8');
274
326
  if (!content.includes('setup-claude-code.sh')) {
275
- content += '\n\n# Claude persistence (added by installer)\n' + onBootLine + '\n';
327
+ content += '\n\n# Claude persistence (added by DATA Tools)\n' + onBootLine + '\n';
276
328
  fs.writeFileSync(replitPath, content);
277
329
  }
278
330
  } else {
279
- fs.writeFileSync(replitPath, '# Claude persistence\n' + onBootLine + '\n');
331
+ fs.writeFileSync(replitPath, '# Claude persistence (DATA Tools)\n' + onBootLine + '\n');
280
332
  }
281
333
 
282
334
  // Update .gitignore (only essential sensitive dirs)
283
335
  console.log('📝 Updating .gitignore...');
284
336
  const gitignorePath = path.join(WORKSPACE, '.gitignore');
285
- const gitignoreEntries = '\n# Claude/Codex credentials (added by replit-tools)\n.claude-persistent/\n.codex-persistent/\n';
337
+ const gitignoreEntries = '\n# Claude/Codex credentials (added by DATA Tools)\n.claude-persistent/\n.codex-persistent/\n';
286
338
 
287
339
  if (fs.existsSync(gitignorePath)) {
288
340
  let content = fs.readFileSync(gitignorePath, 'utf8');
@@ -293,8 +345,9 @@ if (fs.existsSync(gitignorePath)) {
293
345
  fs.writeFileSync(gitignorePath, gitignoreEntries.trim() + '\n');
294
346
  }
295
347
 
296
- // Add PATH to current process for session manager
348
+ // Add PATH and CLAUDE_CONFIG_DIR to current process
297
349
  process.env.PATH = `${localBin}:${process.env.PATH}`;
350
+ process.env.CLAUDE_CONFIG_DIR = claudePersistentDir;
298
351
 
299
352
  console.log('');
300
353
  console.log('╭─────────────────────────────────────────────────────────╮');
@@ -302,18 +355,23 @@ console.log('│ ✅ Installation complete! │');
302
355
  console.log('╰─────────────────────────────────────────────────────────╯');
303
356
  console.log('');
304
357
  console.log('Your conversations and credentials now persist across restarts.');
358
+ console.log(`Claude config directory: ${claudePersistentDir}`);
305
359
  console.log('');
306
360
 
307
361
  // Check if Claude needs login
308
362
  let needsLogin = true;
309
363
  try {
310
- const authCheck = execSync('claude auth status 2>&1 || true', { encoding: 'utf8', shell: '/bin/bash' });
364
+ const authCheck = execSync('claude auth status 2>&1 || true', {
365
+ encoding: 'utf8',
366
+ shell: '/bin/bash',
367
+ env: { ...process.env, CLAUDE_CONFIG_DIR: claudePersistentDir }
368
+ });
311
369
  if (authCheck.includes('Logged in') || authCheck.includes('valid')) {
312
370
  needsLogin = false;
313
371
  }
314
372
  } catch {}
315
373
 
316
- if (needsLogin && !hasReplitSecret('ANTHROPIC_API_KEY')) {
374
+ if (needsLogin && !getReplitSecret('ANTHROPIC_API_KEY')) {
317
375
  console.log('⚠️ Claude needs authentication. Run: claude login');
318
376
  console.log('');
319
377
  }
@@ -325,7 +383,8 @@ console.log('');
325
383
  // Use spawn to run bash interactively with our session manager
326
384
  const sessionManager = spawn('bash', ['--rcfile', path.join(WORKSPACE, '.config/bashrc'), '-i'], {
327
385
  stdio: 'inherit',
328
- cwd: WORKSPACE
386
+ cwd: WORKSPACE,
387
+ env: { ...process.env, CLAUDE_CONFIG_DIR: claudePersistentDir }
329
388
  });
330
389
 
331
390
  sessionManager.on('exit', (code) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "replit-tools",
3
- "version": "1.0.2",
4
- "description": "Persist Claude Code sessions, auth, and history across Replit container restarts",
3
+ "version": "1.0.4",
4
+ "description": "DATA Tools - One command to set up Claude Code and Codex CLI on Replit with full persistence",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "replit-tools": "./index.js"