Skip to content

feat!: v3.0 architecture rewrite — devcontainer primary config, interactive init, settings.json#142

Merged
jeevanpillay merged 7 commits intomainfrom
feature/dual-61-add-devcontainerjson-fallback-config-reader
Feb 16, 2026
Merged

feat!: v3.0 architecture rewrite — devcontainer primary config, interactive init, settings.json#142
jeevanpillay merged 7 commits intomainfrom
feature/dual-61-add-devcontainerjson-fallback-config-reader

Conversation

@jeevanpillay
Copy link
Copy Markdown
Owner

@jeevanpillay jeevanpillay commented Feb 16, 2026

Summary

devcontainer.json as primary config source (DUAL-61)

  • New src/devcontainer.rs parser handling all spec-allowed format variants (string/array/object commands, integer/string ports, string/object mounts)
  • Docker build support via build_image() for build.dockerfile configs

Shell interception pane propagation

  • tmux set-environment propagates DUAL_ACTIVE, DUAL_RC_PATH, DUAL_CONTAINER to new panes/windows
  • Auto-installs idempotent shell hook in ~/.zshrc or ~/.bashrc on first run

Rename dual add to dual init (DUAL-62)

  • Add CLI variant renamed to Init with updated help text
  • All user-facing messages updated

.dual/settings.json config system (DUAL-63, DUAL-65)

  • Replace .dual.toml with .dual/settings.json (JSON format)
  • Two-file config: devcontainer.json (container config) + .dual/settings.json (orchestration config)
  • load_hints() merge pipeline: DualConfig + DevcontainerJson → RepoHints

Interactive init wizard (DUAL-64)

  • New src/init.rs module with dialoguer crate for styled terminal prompts
  • 5-step wizard: detect existing devcontainer → select image → configure ports → setup command → confirm
  • --yes/-y flag for non-interactive mode (CI/scripting)
  • Removed write_default_dual_config() and write_default_devcontainer() from config.rs

All consumers and tests updated (DUAL-66, DUAL-68)

  • Zero .dual.toml or dual add references remain in source code
  • Test fixtures write .dual/settings.json + devcontainer.json
  • README and docs updated

Migration path (DUAL-67)

  • Closed as won't-do — no external users on v2 format

Test plan

  • cargo test — 191 tests pass
  • cargo clippy — clean
  • cargo fmt --check — clean
  • No .dual.toml references in source code
  • Interactive wizard tested with dialoguer prompts
  • --yes flag applies defaults without prompts

Resolves DUAL-61, DUAL-62, DUAL-63, DUAL-64, DUAL-65, DUAL-66, DUAL-67, DUAL-68

Add devcontainer.json as a fallback configuration source when no
.dual.toml exists, giving Dual zero-config compatibility with repos
that already have .devcontainer/ directories.

- New src/devcontainer.rs parser for image, build, forwardPorts,
  containerEnv, postCreateCommand, and mounts fields
- load_hints() fallback chain: .dual.toml → devcontainer.json → defaults
- DockerfileBuild struct and docker build support in container creation
- 30 new unit tests covering all format variants

Resolves: DUAL-61
Entire-Checkpoint: 83e76ce9f6e4
When splitting a pane or creating a new window in a Dual tmux session,
the new shell now auto-loads command interception. Previously, new panes
ran commands on the host instead of the container.

Two mechanisms work together:
- tmux set-environment sets DUAL_ACTIVE, DUAL_RC_PATH, DUAL_CONTAINER
  at the session level so new panes inherit them
- dual add installs a guarded snippet in ~/.zshrc or ~/.bashrc that
  sources the RC file when DUAL_ACTIVE is set

Entire-Checkpoint: 83e76ce9f6e4
@jeevanpillay jeevanpillay changed the title feat: add devcontainer.json fallback config reader feat: devcontainer.json fallback + shell interception pane propagation Feb 16, 2026
…tings

BREAKING CHANGE: Fields `image`, `ports`, `setup`, and `[env]` are
removed from `.dual.toml`. Container configuration now belongs in
`devcontainer.json`, while `.dual.toml` contains only Dual-specific
orchestration fields (extra_commands, anonymous_volumes, shared).

- Add DualConfig struct for .dual.toml (orchestration-only fields)
- Rewrite load_hints() to merge DualConfig + devcontainer.json → RepoHints
- Add write_default_dual_config() and write_default_devcontainer()
- Add migration warning for deprecated fields in .dual.toml
- Update cmd_add() to create both .dual.toml and devcontainer.json
- Update user-facing messages to reference devcontainer.json for ports
- Update test fixtures and README documentation

Entire-Checkpoint: 83e76ce9f6e4
Shell hook is now installed on any dual invocation (idempotent),
not tied to dual add. This matches the user expectation that
the hook is set up at install time, not per-repo registration.

Entire-Checkpoint: 83e76ce9f6e4
… `.dual/settings.json`

DUAL-62: Rename the `add` subcommand to `init` across CLI, dispatch,
user-facing messages, TUI empty state, and README.

DUAL-63: Replace TOML config at `.dual.toml` with JSON config at
`.dual/settings.json`. Remove SharedConfig struct and flatten `shared`
to Vec<String>. Make `devcontainer` a required String field. Add
MissingConfig error variant. Rewrite load/write/parse functions and
all config tests for JSON.

BREAKING CHANGE: `dual add` is now `dual init`. Config file moved from
`.dual.toml` (TOML) to `.dual/settings.json` (JSON) with a new schema.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: bf199bdb28ce
Replace hardcoded defaults in `dual init` with a 5-step interactive
wizard (image selection, ports, setup command, summary/confirm).
Add --yes/-y flag for non-interactive mode. Move file-writing logic
from config.rs into new init module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: cc13ef3e9119
@jeevanpillay jeevanpillay changed the title feat: devcontainer.json fallback + shell interception pane propagation feat!: v3.0 architecture rewrite — devcontainer primary config, interactive init, settings.json Feb 16, 2026
@jeevanpillay jeevanpillay merged commit 0c12be4 into main Feb 16, 2026
8 checks passed
@jeevanpillay jeevanpillay deleted the feature/dual-61-add-devcontainerjson-fallback-config-reader branch February 16, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants