Add a New Tool
This guide walks through adding each type of tool to your datamitsu configuration.
Adding a Binary App
Binary apps are standalone executables downloaded directly from release URLs.
1. Find the release URLs
Locate the download URLs for each platform you need. Most tools publish releases on GitHub with platform-specific archives.
2. Obtain and verify the SHA-256 hashes
Obtain each archive's SHA-256 from an authenticated upstream release manifest or signature before downloading it. Never treat a digest computed only after an untrusted download as the trust anchor. Then verify the download against that expected value:
EXPECTED_SHA256="<sha256-from-the-upstream-manifest>"
curl -L -o tool.tar.gz "https://github.com/org/tool/releases/download/v1.0.0/tool_linux_amd64.tar.gz"
printf '%s %s\n' "$EXPECTED_SHA256" tool.tar.gz | sha256sum --check -
3. Add the app definition
Add the app to apps in your config file:
/// <reference path=".datamitsu/datamitsu.config.d.ts" />
function getConfig(config) {
return {
...config,
apps: {
...config.apps,
mytool: {
binary: {
binaries: {
darwin: {
amd64: {
unknown: {
url: "https://github.com/org/mytool/releases/download/v1.0.0/mytool_darwin_amd64.tar.gz",
hash: "sha256:<digest>",
contentType: "tar.gz",
binaryPath: "mytool",
},
},
arm64: {
unknown: {
url: "https://github.com/org/mytool/releases/download/v1.0.0/mytool_darwin_arm64.tar.gz",
hash: "sha256:<digest>",
contentType: "tar.gz",
binaryPath: "mytool",
},
},
},
linux: {
amd64: {
glibc: {
url: "https://github.com/org/mytool/releases/download/v1.0.0/mytool_linux_amd64.tar.gz",
hash: "sha256:<digest>",
contentType: "tar.gz",
binaryPath: "mytool",
},
},
},
},
},
},
},
};
}
globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";
4. Test the tool
datamitsu init
datamitsu exec mytool -- --version
5. Verify cross-platform hashes (optional)
Use devtools verify-all to download and verify hashes for all configured platforms:
datamitsu devtools verify-all
Adding a UV App (Python)
UV apps are Python packages installed in isolated environments.
1. Find the package on PyPI
Check that your tool is available on PyPI and note the version.
2. Add the app definition
/// <reference path=".datamitsu/datamitsu.config.d.ts" />
function getConfig(config) {
return {
...config,
apps: {
...config.apps,
yamllint: {
uv: {
packageName: "yamllint",
version: "1.35.1",
},
},
},
};
}
globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";
The runtime field references a UV runtime defined in runtimes. The default configuration already includes one.
3. Generate the mandatory lock file
The config lockfile command deliberately permits this app's initially missing
lockFile so it can generate one. All normal commands reject the config until
you paste the result back:
datamitsu config lockfile yamllint
Copy the output into your app definition:
yamllint: {
uv: {
packageName: "yamllint",
version: "1.35.1",
lockFile: "br:...", // paste the output here
},
},
4. Test the tool
datamitsu init
datamitsu exec yamllint -- --version
Adding a Bun App
Bun apps are npm packages installed by pnpm and executed with an isolated Bun runtime. Bun launches the pnpm script directly, so no Node runtime is acquired for installation.
1. Add the app definition
apps: {
eslint: {
bun: {
packageName: "eslint",
version: "10.9.0",
binPath: "node_modules/eslint/bin/eslint.js",
lockFile: "", // generated next
},
},
}
Use the package's JavaScript entrypoint for binPath. datamitsu invokes it explicitly with Bun rather than relying on an npm .bin shebang that may select Node.
2. Generate the mandatory lock file
datamitsu config lockfile eslint
Paste the resulting br:... value into lockFile. It contains pnpm-lock.yaml; normal installs use pnpm's frozen lockfile and the shared hardened workspace policy.
3. Test the tool
datamitsu exec eslint -- --version
Adding a Node App (Node.js)
Node apps are npm packages managed with pnpm in isolated Node.js environments.
1. Find the package on npm
Check that your tool is available on npm and note the version.
2. Add the app definition
/// <reference path=".datamitsu/datamitsu.config.d.ts" />
function getConfig(config) {
return {
...config,
apps: {
...config.apps,
prettier: {
node: {
packageName: "prettier",
version: "3.2.0",
binPath: "node_modules/.bin/prettier",
},
},
},
};
}
globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";
3. Generate the mandatory lock file
datamitsu config lockfile prettier
Add the output to your app definition as the lockFile field.
4. Add managed config links (optional)
If the app provides configuration files that your projects need, add links:
prettier: {
node: {
packageName: "prettier",
version: "3.2.0",
binPath: "node_modules/.bin/prettier",
lockFile: "br:...",
},
links: {
"prettier-config": "dist/prettier.config.js",
},
},
After datamitsu init, this creates a symlink at .datamitsu/prettier-config pointing to the file inside the app's install directory.
5. Test the tool
datamitsu init
datamitsu exec prettier -- --version
Adding a JVM App
JVM apps are JAR files executed with a managed JDK.
1. Find the JAR URL
Locate the direct download URL for the JAR file, typically from Maven Central or the project's releases.
2. Obtain the SHA-256 hash
Obtain the digest from the repository's authenticated checksum metadata or a
signed upstream release manifest. As with binary apps, set jarHash — a
canonical sha256:<64 lowercase hex> digest — before allowing datamitsu to
download the JAR; a missing hash is a config error.
3. Add the app definition
/// <reference path=".datamitsu/datamitsu.config.d.ts" />
function getConfig(config) {
return {
...config,
apps: {
...config.apps,
"openapi-generator": {
jvm: {
jarUrl:
"https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/7.0.0/openapi-generator-cli-7.0.0.jar",
jarHash: "sha256:...", // canonical digest (mandatory)
version: "7.0.0",
},
},
},
};
}
globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";
4. Test the tool
datamitsu init
datamitsu exec openapi-generator version
Adding a Go App
Go apps are built from a pinned module version with a managed, hash-verified Go
SDK. Their lock payload contains both go.mod and go.sum.
1. Add the package and version
The initial definition may omit lockFile only while running the generation
command:
/// <reference path=".datamitsu/datamitsu.config.d.ts" />
function getConfig(config) {
return {
...config,
apps: {
...config.apps,
govulncheck: {
go: {
packageName: "golang.org/x/vuln/cmd/govulncheck",
version: "v1.3.0",
},
},
},
};
}
globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";
2. Generate the mandatory lock file
datamitsu config lockfile govulncheck
Paste the output into the app:
govulncheck: {
go: {
packageName: "golang.org/x/vuln/cmd/govulncheck",
version: "v1.3.0",
lockFile: "br:...", // contains go.mod + go.sum
},
},
The subsequent build uses go build -trimpath -mod=readonly; dependency drift
that would modify either module file fails instead.
3. Test the tool
datamitsu init
datamitsu exec govulncheck -- --version
Wiring a Tool to the Tooling System
After adding an app, you can wire it into the fix/lint/check workflow by adding a tool definition:
const tools = {
...config.tools,
mytool: {
name: "mytool",
projectTypes: ["golang-package"],
operations: {
lint: {
app: "mytool",
args: ["check", "{files}"],
scope: "per-project",
globs: ["**/*.go"],
},
fix: {
app: "mytool",
args: ["fix", "{files}"],
scope: "per-project",
globs: ["**/*.go"],
},
},
},
};
Now datamitsu check will include your tool in its workflow. See the Tooling System guide for details on scopes, placeholders, and environment variables.
Version Checks
Add a versionCheck to enable datamitsu devtools verify-all to check your tool:
mytool: {
binary: {
// ... binaries definition
},
versionCheck: {
args: ["version"], // default is ["--version"]
},
}
Set versionCheck: { disabled: true } for tools that don't support version reporting.