Skip to content

.dual/settings.json config system #144

@jeevanpillay

Description

@jeevanpillay

Summary

Replace .dual.toml with .dual/settings.json as the per-repo config file. The .dual/ folder is committed to git and becomes the extensible root for all Dual configuration.

Moving from TOML to JSON for long-term extensibility and ecosystem alignment (devcontainer.json is already JSON).

Breaking Change

.dual.toml is replaced by .dual/settings.json. The DualConfig struct switches from TOML to JSON serde.

Schema

{
  "devcontainer": ".devcontainer/devcontainer.json",
  "extra_commands": ["cargo", "go"],
  "anonymous_volumes": ["node_modules", ".next"],
  "shared": [".env.local", ".vercel"]
}

Key rule: devcontainer field must always be explicitly set in settings.json. No implicit auto-detection — the init flow handles setting it up.

Implementation

1. New DualConfig struct (JSON-based)

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct DualConfig {
    pub devcontainer: String,
    #[serde(default)]
    pub extra_commands: Vec<String>,
    #[serde(default = "default_anonymous_volumes")]
    pub anonymous_volumes: Vec<String>,
    #[serde(default)]
    pub shared: Vec<String>,
}

Changes from current model:

  • devcontainer is String (required), not Option<String>
  • shared flattened from SharedConfig { files } to just Vec<String>
  • Serialization via serde_json instead of toml

2. File paths

  • Config dir: {repo_root}/.dual/
  • Config file: {repo_root}/.dual/settings.json
  • Constants: DUAL_DIR = ".dual", SETTINGS_FILENAME = "settings.json"

3. Functions to add/update

  • load_dual_config() — reads .dual/settings.json (error if missing, not defaults)
  • write_dual_config() — writes .dual/settings.json (pretty-printed JSON)
  • ensure_dual_dir() — creates .dual/ directory
  • Remove TOML dependency for config (keep for global state)

4. load_hints() update

Still merges DualConfig + devcontainer.json → RepoHints, but:

  • Reads from .dual/settings.json instead of .dual.toml
  • Uses the explicit devcontainer path (no auto-detection fallback)
  • Error if .dual/settings.json is missing (user must run dual init)

Tests

  • Parse/write roundtrip for JSON-based DualConfig
  • load_hints() merge with new paths
  • Missing .dual/settings.json returns appropriate error
  • Schema validation (required devcontainer field)

Metadata

Metadata

Assignees

Labels

coreCore functionality

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions