12 KiB
Crate Migration Guide: codex-rs to code-rs
This guide documents the process for moving shared crates from codex-rs into code-rs, making them fully independent.
Overview
The code-rs repository currently contains thin wrapper crates that re-export functionality from their codex-rs counterparts. This creates a cross-repository dependency via relative paths (../codex-rs/...). The migration process moves the implementation into code-rs so that the crate owns its code and no longer depends on codex-rs.
Case Study: linux-sandbox Migration
We successfully migrated code-linux-sandbox as a representative example. This crate had:
- Multiple source modules (landlock.rs, linux_run_main.rs)
- A binary entry point (main.rs)
- Integration tests
- Platform-specific dependencies (Linux only)
- Dependencies on
codex-core(which had already been migrated tocode-core)
Migration Pattern
1. Pre-Migration Analysis
Before starting, understand:
- Source crate location:
/home/azureuser/code/codex-rs/<crate-name>/ - Destination crate location:
/home/azureuser/code/code-rs/<crate-name>/ - Current wrapper structure: Usually just
pub use codex_<crate>::*; - Dependencies: What other crates does this depend on?
- Consumers: What crates in code-rs depend on this wrapper?
2. File Structure Migration
Copy all implementation files from codex-rs to code-rs:
# Source modules (excluding lib.rs which needs special handling)
cp codex-rs/<crate>/src/*.rs code-rs/<crate>/src/
# Exception: main.rs will need modification
# Tests (if they exist)
cp -r codex-rs/<crate>/tests/ code-rs/<crate>/tests/
Files to copy:
- All source modules:
src/*.rs(exceptlib.rs- see below) - Test files:
tests/**/*.rs - Integration test structure:
tests/all.rs,tests/suite/
3. Update Cargo.toml
Replace the wrapper dependency with actual implementation dependencies.
Before (wrapper):
[dependencies]
codex-linux-sandbox = { workspace = true }
After (independent):
[target.'cfg(target_os = "linux")'.dependencies]
clap = { workspace = true, features = ["derive"] }
code-core = { workspace = true } # Note: codex-core → code-core
landlock = { workspace = true }
libc = { workspace = true }
seccompiler = { workspace = true }
[target.'cfg(target_os = "linux")'.dev-dependencies]
tempfile = { workspace = true }
tokio = { workspace = true, features = ["io-std", "macros", "process", "rt-multi-thread", "signal"] }
Key considerations:
- Copy ALL dependency sections from codex-rs Cargo.toml
- Replace
codex-*dependencies withcode-*equivalents where they exist - Keep the same features and version constraints
- Include both
[dependencies]and[dev-dependencies] - Handle platform-specific dependencies (e.g.,
[target.'cfg(target_os = "linux")'.dependencies])
4. Update lib.rs
Replace the wrapper re-export with the actual module structure.
Before (wrapper):
//! Thin wrapper around the upstream `codex-linux-sandbox` crate.
pub use codex_linux_sandbox::*;
After (independent):
#[cfg(target_os = "linux")]
mod landlock;
#[cfg(target_os = "linux")]
mod linux_run_main;
#[cfg(target_os = "linux")]
pub fn run_main() -> ! {
linux_run_main::run_main();
}
#[cfg(not(target_os = "linux"))]
pub fn run_main() -> ! {
panic!("code-linux-sandbox is only supported on Linux");
}
Key considerations:
- Copy the exact module structure from
codex-rs/<crate>/src/lib.rs - Keep platform-specific conditional compilation (
#[cfg(...)]) - Preserve all public exports
- Update any codex-specific naming to code-specific
5. Update main.rs (if binary)
Change the namespace from codex_* to code_*.
Before:
fn main() -> ! {
codex_linux_sandbox::run_main()
}
After:
/// Note that the cwd, env, and command args are preserved in the ultimate call
/// to `execv`, so the caller is responsible for ensuring those values are
/// correct.
fn main() -> ! {
code_linux_sandbox::run_main()
}
6. Update Source Files: Replace Namespace References
Replace all codex_* module references with code_* equivalents:
# Example: Update codex_core to code_core
find code-rs/<crate>/src -name '*.rs' -exec sed -i 's/codex_core/code_core/g' {} +
# Update codex_<crate> to code_<crate> (with underscores)
find code-rs/<crate>/src -name '*.rs' -exec sed -i 's/codex_linux_sandbox/code_linux_sandbox/g' {} +
Common replacements:
use codex_core::→use code_core::codex_core::error::Result→code_core::error::Resultcodex_core::protocol::SandboxPolicy→code_core::protocol::SandboxPolicy
Files that commonly need updates:
- Module implementation files (e.g.,
landlock.rs,linux_run_main.rs) - Any file that imports from other crates
- Test files that reference the crate's types
7. Update Workspace Cargo.toml
Remove the cross-repository dependency reference.
Location: /home/azureuser/code/code-rs/Cargo.toml
Before:
[workspace.dependencies]
# ...
codex-linux-sandbox = { path = "../codex-rs/linux-sandbox" }
# ...
After:
[workspace.dependencies]
# ... (line removed)
8. Build and Verify
# Build the migrated crate
cd /home/azureuser/code/code-rs
cargo build -p code-<crate-name>
# Run tests
cargo test -p code-<crate-name>
# Build dependent crates (e.g., code-arg0 depends on code-linux-sandbox)
cargo build -p <dependent-crate>
Success criteria:
cargo build -p code-<crate>compiles without errors- Tests pass (if applicable)
- Dependent crates still build correctly
- No references to
codex-<crate>remain in the migrated crate
Automated Migration Script
Use the provided script for initial file copying:
cd /home/azureuser/code/code-rs
./migrate-crate.sh <crate-name>
The script will:
- Copy source files from codex-rs to code-rs
- Copy test files
- Display the dependencies you need to add
- Provide a checklist of manual steps
Note: The script handles the tedious file copying but requires manual steps for:
- Updating Cargo.toml dependencies
- Modifying lib.rs and main.rs
- Replacing namespace references
- Updating workspace configuration
Common Pitfalls and Solutions
Pitfall 1: Missing Dependencies
Symptom: Build fails with "cannot find crate" errors.
Solution: Ensure ALL dependencies from the codex-rs Cargo.toml are copied to code-rs Cargo.toml, including:
- Platform-specific dependencies (
[target.'cfg(...)'.dependencies]) - Dev dependencies for tests
- Feature flags on dependencies
Example:
# Don't forget platform-specific dependencies!
[target.'cfg(target_os = "linux")'.dependencies]
libc = { workspace = true }
Pitfall 2: Incomplete Namespace Replacement
Symptom: Build fails with "use of undeclared crate or module codex_*" errors.
Solution: Search for ALL occurrences of codex_ in the migrated crate:
grep -r "codex_" code-rs/<crate>/src/
grep -r "codex_" code-rs/<crate>/tests/
Replace with the appropriate code_* variant. Common locations:
usestatements- Type annotations
- Function calls
- Comments and documentation (optional but recommended)
Pitfall 3: Forgetting Platform-Specific Compilation
Symptom: Build succeeds but runtime behavior is incorrect, or code compiles on wrong platforms.
Solution: Preserve ALL #[cfg(...)] attributes from the original:
#[cfg(target_os = "linux")] // Don't forget these!
mod landlock;
#[cfg(not(target_os = "linux"))]
pub fn run_main() -> ! {
panic!("code-linux-sandbox is only supported on Linux");
}
Pitfall 4: Test Directory Structure
Symptom: Tests don't compile or can't find test modules.
Solution: Copy the ENTIRE test directory structure, including:
tests/all.rs(integration test entry point)tests/suite/directory with all modulestests/suite/mod.rs(module aggregation)
The pattern in codex-rs uses a single integration test binary:
// tests/all.rs
mod suite;
// tests/suite/mod.rs
mod landlock;
mod other_test_modules;
Pitfall 5: Workspace Dependency Conflicts
Symptom: Cargo complains about duplicate dependencies or conflicting versions.
Solution:
- Remove the
codex-<crate>dependency from workspace Cargo.toml - Ensure
code-<crate>is already defined in workspace dependencies - If dependents break, they may need to be updated to use the new independent crate
Pitfall 6: Binary Crates with Libraries
Symptom: Binary doesn't link or can't find library functions.
Solution: Ensure BOTH lib and bin are defined in Cargo.toml:
[lib]
name = "code_linux_sandbox" # Note: underscores
path = "src/lib.rs"
[[bin]]
name = "code-linux-sandbox" # Note: hyphens
path = "src/main.rs"
The binary name uses hyphens, the library name uses underscores (Rust convention).
Dependency Migration Order
Crates should be migrated in dependency order. Dependencies must be migrated before their dependents.
Already migrated:
- ✅
code-core(wascodex-core) - ✅
code-linux-sandbox(wascodex-linux-sandbox)
Remaining wrappers (identified order):
-
Low-level utilities (no codex dependencies):
ansi-escape(identical implementation, trivial)git-apply(minimal dependencies)
-
Process/system level:
process-hardening(may depend on core)execpolicy(depends on core, process-hardening)
-
Networking/client:
backend-client(depends on core)cloud-tasks-client(depends on backend-client)responses-api-proxy(depends on backend-client)
Note: Run grep -r "codex-" code-rs/*/Cargo.toml to see current wrapper dependencies.
Verification Checklist
After migration, verify:
cargo build -p code-<crate>succeedscargo test -p code-<crate>succeeds (if tests exist)- No
codex-<crate>dependency remains in workspace Cargo.toml - No
use codex_*imports remain in src/ (except for unavoidable upstream deps) - All dependent crates still build:
cargo build -p <dependent> - Binary crates (if any) execute correctly
- Tests copied from codex-rs still pass
- Platform-specific behavior preserved (if applicable)
File Checklist for Migration
For each crate, ensure you handle:
Cargo.toml- Dependencies, features, and metadatasrc/lib.rs- Main library module structuresrc/main.rs- Binary entry point (if applicable)src/*.rs- All implementation modulestests/all.rs- Integration test entry point (if exists)tests/suite/*.rs- Individual test modules (if exists)- Workspace
Cargo.toml- Remove codex-* reference - Dependent crates - Verify they still build
Summary
The migration process transforms a thin wrapper crate into a fully independent implementation by:
- Copying implementation files from codex-rs to code-rs
- Updating Cargo.toml with actual dependencies (replacing codex-* with code-*)
- Replacing wrapper re-exports with actual module structure in lib.rs
- Renaming namespaces from codex_* to code_* throughout the code
- Removing the codex- dependency from workspace Cargo.toml
- Building and verifying the migrated crate and its dependents
The result is a crate that owns its implementation and no longer depends on ../codex-rs, making code-rs more independent and easier to maintain.
linux-sandbox Migration Results
The code-linux-sandbox crate was successfully migrated:
- Build status: ✅ Success (
cargo build -p code-linux-sandboxin 1m 50s) - Files migrated: 7 files (lib.rs, main.rs, landlock.rs, linux_run_main.rs, + 3 test files)
- Dependencies: 5 external + 1 internal (code-core)
- Namespace changes: 4 occurrences (codex_core → code_core, codex_linux_sandbox → code_linux_sandbox)
- Workspace change: Removed 1 line from workspace Cargo.toml
The crate now compiles independently without any reference to codex-rs.