# datamitsu

> Opinionated configuration management, extensible by design

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

> **Alpha**: This project is in alpha. The configuration API is not yet stabilized and may change between versions.

## License

MIT - See [LICENSE](LICENSE) for details

## Contributing

This project is in early development. Contribution guidelines will be established as the project matures.

## Configuration Loading

datamitsu loads configuration in layers, each receiving the previous layer's result as input:

```text
default (embedded config.js)
  ↓
--before-config flags  (for library wrappers — runs before project config)
  ↓
auto-discovered  datamitsu.config.js,  datamitsu.config.mjs  or  datamitsu.config.ts  at git root
  ↓
--config flags  (for CI overrides — runs after project config)
  ↓
final merged Config
```

Each layer calls `getConfig(prevConfig)` and returns a new config that extends or overrides the previous one.

### Remote configs (inheritance)

Any config file can declare upstream configs it inherits from:

```ts
export function getRemoteConfigs() {
  return [{ url: "https://example.com/shared-base.ts", hash: "sha256:abcdef..." }];
}
```

The `hash` field (SHA-256) is **required** — datamitsu will refuse to download any remote config without it. Remote configs are resolved **before** `getConfig` is called on the current file — they are parents, not children. Remote configs can themselves have `getRemoteConfigs`, so the resolution is recursive depth-first.

### Library/wrapper pattern

A library that wraps datamitsu passes its config via `--before-config`. The project's auto-discovered `datamitsu.config.ts` naturally overrides it:

```text
library-base.ts  →  project/datamitsu.config.ts  →  final Config
```

## Global Cache Structure

datamitsu stores all cached data under `~/.cache/datamitsu/` (or `$XDG_CACHE_HOME/datamitsu/`):

```text
~/.cache/datamitsu/
├── .bin/                         # Downloaded binaries
├── .runtimes/                    # Runtime binaries (UV, FNM, JVM)
├── .apps/                        # Runtime-managed applications
├── .pnpm-store/                  # Shared PNPM content-addressable store
└── projects/                     # Per-project caches
    └── {blake2b(gitRoot)}/       # Project directory (keyed by BLAKE2b hash)
        ├── toolstate.msgpack     # Lint/fix results cache
        └── cache/                # Tool-specific caches
            └── ...               # e.g., tsbuildinfo for tsc
```

Each project gets its own directory under `projects/`, keyed by a BLAKE2b-256 hash of the git root path. This directory contains both the lint/fix results cache and a `cache/` subdirectory for tool-specific caches.

## Cache Management

```bash
# Clear cache for the current project (lint/fix results + tool caches)
datamitsu cache clear

# Clear cache for all projects
datamitsu cache clear --all

# Preview what would be deleted (dry-run)
datamitsu cache clear --dry-run

# Show the global cache directory path
datamitsu cache path

# Show the current project's cache directory path
datamitsu cache path project
```

By default, `cache clear` clears only the current project's cache, which includes:

- Lint/fix results (`projects/{hash}/toolstate.msgpack`)
- Tool-specific caches (`projects/{hash}/cache/`)

Use `--all` to clear caches for all projects. Use `--dry-run` to preview what would be deleted without actually deleting anything.

## Template Placeholders

Tool arguments and paths in configurations support template placeholders that are resolved at execution time:

| Placeholder   | Resolves To                             | Example                     |
| ------------- | --------------------------------------- | --------------------------- |
| `{cwd}`       | Per-project working directory           | `"{cwd}/src"`               |
| `{root}`      | Git repository root                     | `"{root}/.config"`          |
| `{toolCache}` | Per-project, per-tool cache directory   | `"{toolCache}/tsbuildinfo"` |
| `{file}`      | Single file path (per-file scope tools) | `"{file}"`                  |
| `{files}`     | Space-separated file list               | `"{files}"`                 |

### Using Project Cache in Configurations

Tools that maintain their own cache (e.g., `tsc` with `--incremental`) can use the `{toolCache}` placeholder to store cache files in the correct location:

```ts
tsc: {
  name: "Tsc",
  operations: {
    lint: {
      args: [
        "--noEmit",
        "--incremental",
        "--tsBuildInfoFile",
        "{toolCache}/tsbuildinfo",
      ],
      command: "tsc",
      globs: ["**/*.ts", "**/*.tsx"],
      scope: "per-project",
    },
  },
},
```

This ensures that:

1. Tool caches are isolated per project and per tool (`~/.cache/datamitsu/projects/{hash}/cache/{projectPath}/{toolName}/`)
2. In monorepos, each project gets its own cache namespace (e.g., `cache/packages/frontend/tsc/`, `cache/packages/backend/tsc/`)
3. Repository-scope tools use `cache/{toolName}/` (no project path component)
4. `cache clear` correctly cleans up tool caches alongside lint/fix results
5. Tool caches don't pollute `node_modules` or other project directories

### Facts API vs Templates

The `facts()` function provides platform and environment information for conditional logic in configs:

- `facts().os`, `facts().arch` - Platform detection
- `facts().isInGitRepo`, `facts().isMonorepo` - Git state
- `facts().packageName`, `facts().binaryCommand`, `facts().binaryPath` - Binary info
- `facts().env` - Environment variables

All path references use template placeholders instead. The following facts fields have been removed (breaking change):

- `facts().cwd` - use `{cwd}` template
- `facts().gitRoot` - use `{root}` template
- `facts().projectRoot` - use `{root}` template
- `facts().projectCachePath` - use `{toolCache}` template

## Examples

Usage examples for runtime-managed apps (multi-version isolation, UV isolation, PNPM plugins) are in [examples/](examples/).

## Research & References

For research notes and tool references, see [docs/research.md](docs/research.md).
