@gengjiawen/os-init 1.9.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.11.0](https://github.com/gengjiawen/os-init/compare/v1.10.0...v1.11.0) (2025-12-31)
4
+
5
+
6
+ ### Features
7
+
8
+ * update model version in Codex config template from gpt-5.1 to gpt-5.2 ([56c36d3](https://github.com/gengjiawen/os-init/commit/56c36d3da5c3732100c090c4df3318b5cdd003cf))
9
+
10
+ ## [1.10.0](https://github.com/gengjiawen/os-init/compare/v1.9.1...v1.10.0) (2025-12-06)
11
+
12
+
13
+ ### Features
14
+
15
+ * add command to set up Fish shell import script ([8418406](https://github.com/gengjiawen/os-init/commit/841840694783a1264733b7b8415cdb12d2bb21fa))
16
+ * add dev tun to setup ([a373417](https://github.com/gengjiawen/os-init/commit/a373417ca60f0f1554c85c06d73c017bc722fdf3))
17
+ * add ownership fix for gitpod user config and cache in init script ([dd3720c](https://github.com/gengjiawen/os-init/commit/dd3720cd0a57b603d1cc74179187669e3659ae82))
18
+ * persist ssh host keys via init script and mount gitconfig ([dbaabe9](https://github.com/gengjiawen/os-init/commit/dbaabe98ca44aa3e1cdb29deb12f700a4b559fb5))
19
+
3
20
  ## [1.9.1](https://github.com/gengjiawen/os-init/compare/v1.9.0...v1.9.1) (2025-11-26)
4
21
 
5
22
 
package/README.md CHANGED
@@ -50,6 +50,28 @@ pnpx @gengjiawen/os-init set-android --android-home ~/my-android-sdk
50
50
  pnpx @gengjiawen/os-init set-android --skip-env-vars
51
51
  ```
52
52
 
53
+ ### Setup Fish Shell Import Script
54
+
55
+ ```bash
56
+ pnpx @gengjiawen/os-init set-fish
57
+ ```
58
+
59
+ Sets up Fish shell to automatically import environment variables from `.bashrc`. This command will:
60
+
61
+ - Detect if Fish shell is installed (by checking for `~/.config/fish/config.fish`)
62
+ - Add an import script to `~/.config/fish/config.fish` that reads environment variables from `~/.bashrc`
63
+ - Automatically convert Bash-style environment variable syntax to Fish shell syntax
64
+ - Handle PATH variables correctly (converting `:` separators to spaces)
65
+ - Skip if the import script already exists
66
+
67
+ This is useful when you have environment variables configured in `.bashrc` but want to use them in Fish shell without duplicating configuration.
68
+
69
+ Example:
70
+
71
+ ```bash
72
+ pnpx @gengjiawen/os-init set-fish
73
+ ```
74
+
53
75
  ---
54
76
 
55
77
  ### Configure Claude Code
@@ -58,11 +80,10 @@ pnpx @gengjiawen/os-init set-android --skip-env-vars
58
80
  pnpx @gengjiawen/os-init set-cc <API_KEY>
59
81
  ```
60
82
 
61
- Configures Claude Code Router with your API key. This command will:
83
+ Configures Claude Code with your API key. This command will:
62
84
 
63
- - Write `~/.claude-code-router/config.json`
64
85
  - Write `~/.claude/settings.json`
65
- - Install global tools: `@anthropic-ai/claude-code`, `@musistudio/claude-code-router`
86
+ - Install global tool: `@anthropic-ai/claude-code`
66
87
 
67
88
  ### Configure Codex CLI
68
89
 
package/bin/bin.js CHANGED
@@ -10,12 +10,13 @@ const {
10
10
  setupDevEnvironment,
11
11
  setupAndroidEnvironment,
12
12
  } = require('../build')
13
+ const { appendFishImportScript } = require('../build/fish-shell-utils')
13
14
 
14
15
  const program = new Command()
15
16
 
16
17
  program
17
18
  .command('set-cc')
18
- .description('setup claude-code-router')
19
+ .description('setup Claude Code')
19
20
  .argument('<apiKey>', 'API key to set')
20
21
  .action(async (apiKey) => {
21
22
  // Ensure apiKey is provided
@@ -25,8 +26,7 @@ program
25
26
  return
26
27
  }
27
28
  try {
28
- const { routerConfigPath, settingsPath } = writeClaudeConfig(apiKey)
29
- console.log(`Claude router config written to: ${routerConfigPath}`)
29
+ const { settingsPath } = writeClaudeConfig(apiKey)
30
30
  console.log(`Claude settings written to: ${settingsPath}`)
31
31
  await installDeps()
32
32
  } catch (err) {
@@ -34,7 +34,7 @@ program
34
34
  process.exit(1)
35
35
  }
36
36
  console.log(
37
- 'Claude code is ready, use `claude` in terminal to start building'
37
+ 'Claude Code is ready, use `claude` in terminal to start building'
38
38
  )
39
39
  })
40
40
 
@@ -128,4 +128,17 @@ program
128
128
  }
129
129
  })
130
130
 
131
+ program
132
+ .command('set-fish')
133
+ .description('setup Fish shell to import environment variables from .bashrc')
134
+ .action(async () => {
135
+ try {
136
+ appendFishImportScript()
137
+ console.log('\n✅ Fish shell import script setup completed!')
138
+ } catch (err) {
139
+ console.error('Failed to setup Fish shell:', err.message)
140
+ process.exit(1)
141
+ }
142
+ })
143
+
131
144
  program.parse(process.argv)
@@ -52,7 +52,7 @@ function getAndroidEnvVars(androidHome, ndkVersion) {
52
52
  export ANDROID_HOME=${androidHome}
53
53
  export ANDROID_SDK_ROOT=\${ANDROID_HOME}
54
54
  export ANDROID_NDK_HOME=\${ANDROID_HOME}/ndk/${ndkVersion}
55
- export PATH=\${ANDROID_HOME}/cmdline-tools/bin:\${ANDROID_HOME}/cmdline-tools/latest/bin:\${ANDROID_HOME}/emulator:\${ANDROID_HOME}/platform-tools:\${ANDROID_HOME}/tools:\${ANDROID_HOME}/tools/bin:\${PATH}
55
+ export PATH=\${PATH}:\${ANDROID_HOME}/cmdline-tools/bin:\${ANDROID_HOME}/cmdline-tools/latest/bin:\${ANDROID_HOME}/emulator:\${ANDROID_HOME}/platform-tools:\${ANDROID_HOME}/tools:\${ANDROID_HOME}/tools/bin
56
56
  # ===== Android development environment - END =====
57
57
  `;
58
58
  }
@@ -77,7 +77,6 @@ function hasAndroidEnvVars(rcFile) {
77
77
  return content.includes('ANDROID_HOME');
78
78
  }
79
79
  function appendEnvVarsToShellConfig(rcFile, envVars) {
80
- const shell = process.env.SHELL || '';
81
80
  const homeDir = os.homedir();
82
81
  const bashrcFile = path.join(homeDir, '.bashrc');
83
82
  if (!fs.existsSync(bashrcFile) ||
@@ -88,9 +87,7 @@ function appendEnvVarsToShellConfig(rcFile, envVars) {
88
87
  else {
89
88
  console.log(`Environment variables already exist in: ${bashrcFile}`);
90
89
  }
91
- if (shell.includes('fish')) {
92
- (0, fish_shell_utils_1.appendFishImportScript)();
93
- }
90
+ (0, fish_shell_utils_1.appendFishImportScript)();
94
91
  }
95
92
  async function setupAndroidEnvironment(options) {
96
93
  const androidHome = options?.androidHome || getDefaultAndroidHome();
@@ -191,6 +188,7 @@ async function setupAndroidEnvironment(options) {
191
188
  appendEnvVarsToShellConfig(shellRcFile, envVars);
192
189
  envVarsAdded = true;
193
190
  }
191
+ (0, fish_shell_utils_1.appendFishImportScript)();
194
192
  console.log('\n📋 To activate the environment in your current shell, run:');
195
193
  console.log(` source ${shellRcFile}`);
196
194
  }
@@ -5,6 +5,7 @@ const fs = require("fs");
5
5
  const path = require("path");
6
6
  const execa_1 = require("execa");
7
7
  const ip = require("ip");
8
+ const yaml = require("yaml");
8
9
  function ensureDir(dirPath) {
9
10
  fs.mkdirSync(dirPath, { recursive: true });
10
11
  }
@@ -53,6 +54,22 @@ async function setupDevEnvironment(sshPublicKey, targetDir) {
53
54
  else {
54
55
  throw new Error(`Dockerfile not found in ${targetPath}`);
55
56
  }
57
+ const tunDevicePath = '/dev/net/tun';
58
+ const dockerComposePath = path.join(targetPath, 'docker-compose.yml');
59
+ if (fs.existsSync(tunDevicePath) && fs.existsSync(dockerComposePath)) {
60
+ const content = fs.readFileSync(dockerComposePath, 'utf-8');
61
+ const doc = yaml.parse(content);
62
+ if (doc.services) {
63
+ const serviceName = Object.keys(doc.services)[0];
64
+ const service = doc.services[serviceName];
65
+ if (!service.devices?.includes('/dev/net/tun:/dev/net/tun')) {
66
+ service.devices = service.devices || [];
67
+ service.devices.push('/dev/net/tun:/dev/net/tun');
68
+ fs.writeFileSync(dockerComposePath, yaml.stringify(doc));
69
+ console.log('Added /dev/net/tun device to docker-compose.yml');
70
+ }
71
+ }
72
+ }
56
73
  const hasDockerCompose = await commandExists('docker-compose');
57
74
  if (hasDockerCompose) {
58
75
  console.log('\n🐳 Docker Compose detected. Building and starting containers...');
@@ -40,17 +40,14 @@ end
40
40
  function appendFishImportScript() {
41
41
  const homeDir = os.homedir();
42
42
  const fishConfigPath = path.join(homeDir, '.config', 'fish', 'config.fish');
43
- if (!fs.existsSync(fishConfigPath)) {
44
- console.log('Fish shell config not found, skipping fish setup');
45
- return;
46
- }
47
43
  const configDir = path.dirname(fishConfigPath);
48
44
  if (!fs.existsSync(configDir)) {
49
45
  fs.mkdirSync(configDir, { recursive: true });
50
46
  }
51
- const fishContent = fs.existsSync(fishConfigPath)
52
- ? fs.readFileSync(fishConfigPath, 'utf-8')
53
- : '';
47
+ if (!fs.existsSync(fishConfigPath)) {
48
+ fs.writeFileSync(fishConfigPath, '', 'utf-8');
49
+ }
50
+ const fishContent = fs.readFileSync(fishConfigPath, 'utf-8');
54
51
  if (!fishContent.includes('Import environment variables from .bashrc - START')) {
55
52
  const fishScript = getFishImportBashExports();
56
53
  fs.appendFileSync(fishConfigPath, fishScript);
package/build/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export declare function writeClaudeConfig(apiKey: string): {
2
- routerConfigPath: string;
3
2
  settingsPath: string;
4
3
  };
5
4
  export declare function installDeps(): Promise<void>;
package/build/index.js CHANGED
@@ -10,31 +10,9 @@ const fs = require("fs");
10
10
  const path = require("path");
11
11
  const os = require("os");
12
12
  const execa_1 = require("execa");
13
- function getDefaultConfigDir() {
14
- return path.join(os.homedir(), '.claude-code-router');
15
- }
16
13
  function ensureDir(dirPath) {
17
14
  fs.mkdirSync(dirPath, { recursive: true });
18
15
  }
19
- const DEFAULT_TEMPLATE = `{
20
- "Providers": [
21
- {
22
- "name": "jw",
23
- "api_base_url": "https://ai.gengjiawen.com/api/openai/v1/chat/completions",
24
- "api_key": "API_KEY_PLACEHOLDER",
25
- "models": ["code", "free"],
26
- "transformer": {
27
- "use": ["openrouter"]
28
- }
29
- }
30
- ],
31
- "Router": {
32
- "default": "jw,code",
33
- "background": "jw,code",
34
- "think": "jw,code",
35
- "longContext": "jw,code"
36
- }
37
- }`;
38
16
  function getClaudeSettingsDir() {
39
17
  return path.join(os.homedir(), '.claude');
40
18
  }
@@ -54,17 +32,12 @@ const CLAUDE_SETTINGS_TEMPLATE = `{
54
32
  }
55
33
  }`;
56
34
  function writeClaudeConfig(apiKey) {
57
- const routerConfigDir = getDefaultConfigDir();
58
- const routerConfigPath = path.join(routerConfigDir, 'config.json');
59
- ensureDir(routerConfigDir);
60
- const routerContent = DEFAULT_TEMPLATE.replace('API_KEY_PLACEHOLDER', apiKey);
61
- fs.writeFileSync(routerConfigPath, routerContent);
62
35
  const settingsDir = getClaudeSettingsDir();
63
36
  const settingsPath = path.join(settingsDir, 'settings.json');
64
37
  ensureDir(settingsDir);
65
38
  const settingsContent = CLAUDE_SETTINGS_TEMPLATE.replace(/API_KEY_PLACEHOLDER/g, apiKey);
66
39
  fs.writeFileSync(settingsPath, settingsContent);
67
- return { routerConfigPath, settingsPath };
40
+ return { settingsPath };
68
41
  }
69
42
  async function commandExists(command) {
70
43
  try {
@@ -79,10 +52,7 @@ async function commandExists(command) {
79
52
  }
80
53
  }
81
54
  async function installDeps() {
82
- const packages = [
83
- '@anthropic-ai/claude-code',
84
- '@musistudio/claude-code-router',
85
- ];
55
+ const packages = ['@anthropic-ai/claude-code'];
86
56
  const usePnpm = await commandExists('pnpm');
87
57
  if (usePnpm) {
88
58
  console.log('pnpm detected. Installing dependencies with pnpm...');
@@ -98,7 +68,7 @@ function getCodexConfigDir() {
98
68
  return path.join(os.homedir(), '.codex');
99
69
  }
100
70
  const CODEX_CONFIG_TOML_TEMPLATE = `model_provider = "jw"
101
- model = "gpt-5.1"
71
+ model = "gpt-5.2"
102
72
  model_reasoning_effort = "high"
103
73
  disable_response_storage = true
104
74
  preferred_auth_method = "apikey"
@@ -2,6 +2,8 @@ FROM gengjiawen/node-build
2
2
 
3
3
  # SSHD configuration
4
4
  COPY sshd_config /etc/ssh/sshd_config
5
+ COPY init.sh /usr/local/bin/init.sh
6
+ RUN chmod +x /usr/local/bin/init.sh
5
7
 
6
8
  ENV SSH_PUBLIC_KEY="ssh-public-key-placeholder"
7
9
  RUN set -eux; \
@@ -12,5 +12,9 @@ services:
12
12
  - '5173:5173'
13
13
  cap_add:
14
14
  - SYS_PTRACE
15
+ - NET_ADMIN
15
16
  volumes:
16
17
  - .:/pwd
18
+ - ./.ssh_host_keys:/etc/ssh/host_keys
19
+ - ~/.gitconfig:/home/gitpod/.gitconfig:ro
20
+ command: ['/usr/local/bin/init.sh']
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Generate SSH host keys in mounted volume to keep fingerprints stable across rebuilds.
5
+ HOST_KEY_DIR="/etc/ssh/host_keys"
6
+
7
+ mkdir -p "${HOST_KEY_DIR}"
8
+
9
+ for key_type in rsa ed25519; do
10
+ key_path="${HOST_KEY_DIR}/ssh_host_${key_type}_key"
11
+ if [ ! -f "${key_path}" ]; then
12
+ echo "Generating ${key_type} host key..."
13
+ ssh-keygen -q -N "" -t "${key_type}" -f "${key_path}"
14
+ else
15
+ echo "${key_type} host key already exists."
16
+ fi
17
+ done
18
+
19
+ echo "Done. SSH host keys are ready."
20
+
21
+ # Fix ownership for gitpod user config/cache if needed
22
+ TARGET_UID=${TARGET_UID:-33333}
23
+ TARGET_GID=${TARGET_GID:-33333}
24
+ TARGET_HOME=/home/gitpod
25
+
26
+ fix_owner() {
27
+ local dir="$1"
28
+ [ -d "$dir" ] || return 0
29
+ local owner_uid owner_gid
30
+ owner_uid=$(stat -c %u "$dir")
31
+ owner_gid=$(stat -c %g "$dir")
32
+ if [ "$owner_uid" != "$TARGET_UID" ] || [ "$owner_gid" != "$TARGET_GID" ]; then
33
+ chown -R "${TARGET_UID}:${TARGET_GID}" "$dir"
34
+ fi
35
+ }
36
+
37
+ fix_owner "${TARGET_HOME}/.config"
38
+ fix_owner "${TARGET_HOME}/.cache"
39
+
40
+ exec /usr/sbin/sshd -D -e
@@ -1,9 +1,9 @@
1
1
  Port 22
2
2
  Protocol 2
3
3
 
4
- # Host keys are generated at runtime with `ssh-keygen -A`
5
- HostKey /etc/ssh/ssh_host_rsa_key
6
- HostKey /etc/ssh/ssh_host_ed25519_key
4
+ # Host keys are persisted in mounted volume to keep fingerprints stable
5
+ HostKey /etc/ssh/host_keys/ssh_host_rsa_key
6
+ HostKey /etc/ssh/host_keys/ssh_host_ed25519_key
7
7
 
8
8
  SyslogFacility AUTHPRIV
9
9
  LogLevel VERBOSE
@@ -58,7 +58,7 @@ function getAndroidEnvVars(androidHome: string, ndkVersion: string): string {
58
58
  export ANDROID_HOME=${androidHome}
59
59
  export ANDROID_SDK_ROOT=\${ANDROID_HOME}
60
60
  export ANDROID_NDK_HOME=\${ANDROID_HOME}/ndk/${ndkVersion}
61
- export PATH=\${ANDROID_HOME}/cmdline-tools/bin:\${ANDROID_HOME}/cmdline-tools/latest/bin:\${ANDROID_HOME}/emulator:\${ANDROID_HOME}/platform-tools:\${ANDROID_HOME}/tools:\${ANDROID_HOME}/tools/bin:\${PATH}
61
+ export PATH=\${PATH}:\${ANDROID_HOME}/cmdline-tools/bin:\${ANDROID_HOME}/cmdline-tools/latest/bin:\${ANDROID_HOME}/emulator:\${ANDROID_HOME}/platform-tools:\${ANDROID_HOME}/tools:\${ANDROID_HOME}/tools/bin
62
62
  # ===== Android development environment - END =====
63
63
  `
64
64
  }
@@ -88,7 +88,6 @@ function hasAndroidEnvVars(rcFile: string): boolean {
88
88
 
89
89
  /** Append Android environment variables to shell config */
90
90
  function appendEnvVarsToShellConfig(rcFile: string, envVars: string): void {
91
- const shell = process.env.SHELL || ''
92
91
  const homeDir = os.homedir()
93
92
  const bashrcFile = path.join(homeDir, '.bashrc')
94
93
 
@@ -104,9 +103,7 @@ function appendEnvVarsToShellConfig(rcFile: string, envVars: string): void {
104
103
  }
105
104
 
106
105
  // For fish shell, always write to bashrc first, then add import script to fish config
107
- if (shell.includes('fish')) {
108
- appendFishImportScript()
109
- }
106
+ appendFishImportScript()
110
107
  }
111
108
 
112
109
  /** Setup Android development environment */
@@ -265,6 +262,10 @@ export async function setupAndroidEnvironment(options?: {
265
262
  envVarsAdded = true
266
263
  }
267
264
 
265
+ // Always check and add fish import script if fish shell exists
266
+ // This ensures fish users get the import script even if current shell is not fish
267
+ appendFishImportScript()
268
+
268
269
  console.log('\n📋 To activate the environment in your current shell, run:')
269
270
  console.log(` source ${shellRcFile}`)
270
271
  }
package/libs/dev-setup.ts CHANGED
@@ -2,6 +2,7 @@ import * as fs from 'fs'
2
2
  import * as path from 'path'
3
3
  import { execa } from 'execa'
4
4
  import * as ip from 'ip'
5
+ import * as yaml from 'yaml'
5
6
 
6
7
  /** Ensure directory exists */
7
8
  function ensureDir(dirPath: string): void {
@@ -68,6 +69,30 @@ export async function setupDevEnvironment(
68
69
  throw new Error(`Dockerfile not found in ${targetPath}`)
69
70
  }
70
71
 
72
+ // Check if /dev/net/tun exists and add devices to docker-compose.yml
73
+ const tunDevicePath = '/dev/net/tun'
74
+ const dockerComposePath = path.join(targetPath, 'docker-compose.yml')
75
+ if (fs.existsSync(tunDevicePath) && fs.existsSync(dockerComposePath)) {
76
+ const content = fs.readFileSync(dockerComposePath, 'utf-8')
77
+ const doc = yaml.parse(content) as {
78
+ services?: { [key: string]: { devices?: string[] } }
79
+ }
80
+
81
+ // Find the first service and add devices
82
+ if (doc.services) {
83
+ const serviceName = Object.keys(doc.services)[0]
84
+ const service = doc.services[serviceName]
85
+
86
+ // Check if devices already contains /dev/net/tun
87
+ if (!service.devices?.includes('/dev/net/tun:/dev/net/tun')) {
88
+ service.devices = service.devices || []
89
+ service.devices.push('/dev/net/tun:/dev/net/tun')
90
+ fs.writeFileSync(dockerComposePath, yaml.stringify(doc))
91
+ console.log('Added /dev/net/tun device to docker-compose.yml')
92
+ }
93
+ }
94
+ }
95
+
71
96
  // Check if docker-compose is available
72
97
  const hasDockerCompose = await commandExists('docker-compose')
73
98
 
@@ -46,22 +46,19 @@ export function appendFishImportScript(): void {
46
46
  const homeDir = os.homedir()
47
47
  const fishConfigPath = path.join(homeDir, '.config', 'fish', 'config.fish')
48
48
 
49
- // Detect if fish shell exists by checking config file
50
- if (!fs.existsSync(fishConfigPath)) {
51
- console.log('Fish shell config not found, skipping fish setup')
52
- return
53
- }
54
-
55
49
  // Ensure fish config directory exists
56
50
  const configDir = path.dirname(fishConfigPath)
57
51
  if (!fs.existsSync(configDir)) {
58
52
  fs.mkdirSync(configDir, { recursive: true })
59
53
  }
60
54
 
55
+ // Create fish config file if it doesn't exist
56
+ if (!fs.existsSync(fishConfigPath)) {
57
+ fs.writeFileSync(fishConfigPath, '', 'utf-8')
58
+ }
59
+
61
60
  // Check if import script already exists
62
- const fishContent = fs.existsSync(fishConfigPath)
63
- ? fs.readFileSync(fishConfigPath, 'utf-8')
64
- : ''
61
+ const fishContent = fs.readFileSync(fishConfigPath, 'utf-8')
65
62
 
66
63
  if (
67
64
  !fishContent.includes('Import environment variables from .bashrc - START')
package/libs/index.ts CHANGED
@@ -3,37 +3,11 @@ import * as path from 'path'
3
3
  import * as os from 'os'
4
4
  import { execa } from 'execa'
5
5
 
6
- /** Return default configuration directory path */
7
- function getDefaultConfigDir(): string {
8
- return path.join(os.homedir(), '.claude-code-router')
9
- }
10
-
11
6
  /** Ensure directory exists */
12
7
  function ensureDir(dirPath: string): void {
13
8
  fs.mkdirSync(dirPath, { recursive: true })
14
9
  }
15
10
 
16
- /** Template string used for simple string replacement */
17
- const DEFAULT_TEMPLATE = `{
18
- "Providers": [
19
- {
20
- "name": "jw",
21
- "api_base_url": "https://ai.gengjiawen.com/api/openai/v1/chat/completions",
22
- "api_key": "API_KEY_PLACEHOLDER",
23
- "models": ["code", "free"],
24
- "transformer": {
25
- "use": ["openrouter"]
26
- }
27
- }
28
- ],
29
- "Router": {
30
- "default": "jw,code",
31
- "background": "jw,code",
32
- "think": "jw,code",
33
- "longContext": "jw,code"
34
- }
35
- }`
36
-
37
11
  /** Return Claude settings directory path */
38
12
  function getClaudeSettingsDir(): string {
39
13
  return path.join(os.homedir(), '.claude')
@@ -56,18 +30,10 @@ const CLAUDE_SETTINGS_TEMPLATE = `{
56
30
  }
57
31
  }`
58
32
 
59
- /** Write Claude config files (both router config and settings) */
33
+ /** Write Claude config files */
60
34
  export function writeClaudeConfig(apiKey: string): {
61
- routerConfigPath: string
62
35
  settingsPath: string
63
36
  } {
64
- // Write claude-code-router config
65
- const routerConfigDir = getDefaultConfigDir()
66
- const routerConfigPath = path.join(routerConfigDir, 'config.json')
67
- ensureDir(routerConfigDir)
68
- const routerContent = DEFAULT_TEMPLATE.replace('API_KEY_PLACEHOLDER', apiKey)
69
- fs.writeFileSync(routerConfigPath, routerContent)
70
-
71
37
  // Write Claude settings
72
38
  const settingsDir = getClaudeSettingsDir()
73
39
  const settingsPath = path.join(settingsDir, 'settings.json')
@@ -78,7 +44,7 @@ export function writeClaudeConfig(apiKey: string): {
78
44
  )
79
45
  fs.writeFileSync(settingsPath, settingsContent)
80
46
 
81
- return { routerConfigPath, settingsPath }
47
+ return { settingsPath }
82
48
  }
83
49
 
84
50
  /** Check if a command exists */
@@ -98,10 +64,7 @@ async function commandExists(command: string): Promise<boolean> {
98
64
 
99
65
  /** Install global dependencies */
100
66
  export async function installDeps(): Promise<void> {
101
- const packages = [
102
- '@anthropic-ai/claude-code',
103
- '@musistudio/claude-code-router',
104
- ]
67
+ const packages = ['@anthropic-ai/claude-code']
105
68
  const usePnpm = await commandExists('pnpm')
106
69
 
107
70
  if (usePnpm) {
@@ -121,7 +84,7 @@ function getCodexConfigDir(): string {
121
84
 
122
85
  /** Template for Codex config.toml */
123
86
  const CODEX_CONFIG_TOML_TEMPLATE = `model_provider = "jw"
124
- model = "gpt-5.1"
87
+ model = "gpt-5.2"
125
88
  model_reasoning_effort = "high"
126
89
  disable_response_storage = true
127
90
  preferred_auth_method = "apikey"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gengjiawen/os-init",
3
3
  "private": false,
4
- "version": "1.9.1",
4
+ "version": "1.11.0",
5
5
  "description": "",
6
6
  "main": "index.js",
7
7
  "bin": {
@@ -9,7 +9,6 @@
9
9
  },
10
10
  "scripts": {
11
11
  "dev": "tsc -w",
12
- "server": "nodemon --exec ts-node libs/index.ts",
13
12
  "prepare": "husky",
14
13
  "clean": "rimraf build",
15
14
  "format": "prettier --write \"{examples,libs,script,bin}/**/*.{js,ts}\" \"**/*.yml\"",
@@ -22,7 +21,8 @@
22
21
  "@gengjiawen/unzip-url": "^1.1.0",
23
22
  "commander": "^12.1.0",
24
23
  "ip": "^2.0.1",
25
- "execa": "^8.0.1"
24
+ "execa": "^8.0.1",
25
+ "yaml": "^2.8.2"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
@@ -36,16 +36,16 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/ip": "^1.1.3",
39
- "@types/jest": "29.5.12",
39
+ "@types/jest": "30.0.0",
40
40
  "@types/node": "24.1.0",
41
41
  "cpy-cli": "^6.0.0",
42
42
  "husky": "9.1.6",
43
- "jest": "29.7.0",
43
+ "jest": "30.2.0",
44
44
  "lint-staged": "^15.2.2",
45
45
  "nodemon": "3.1.4",
46
46
  "prettier": "3.5.3",
47
47
  "rimraf": "6.1.2",
48
- "ts-jest": "29.2.4",
48
+ "ts-jest": "29.4.6",
49
49
  "ts-node": "^10.9.1",
50
50
  "typescript": "5.6.3"
51
51
  },