Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **docs**: All install instructions now target `@deepl/cli` (10 occurrences across `docs/SYNC.md`, four example scripts, `examples/README.md`, and the git-hook template in `src/services/git-hooks.ts`). The README installation section documents three install paths — Homebrew (`brew install deepl/tap/deepl`, which manages Node itself), npm (`npm install -g @deepl/cli`), and from source — with an explicit Node.js 24 prerequisite, replacing the `better-sqlite3` native-compilation caveat (Xcode CLT / python3-make-gcc), which no longer applies. The `TROUBLESHOOTING.md` `NODE_MODULE_VERSION` / `npm rebuild better-sqlite3` entry is replaced by accurate guidance for the one remaining cache-degradation cause (running on Node < 24). Six stale `DeepLcom` GitHub URLs now point at the `DeepL` org directly. `CONTRIBUTING.md` states the Node 24 development prerequisite, and `SECURITY.md`'s supported-versions table reflects that only 2.x is a published, supported line.
- **tests**: Jest's haste map no longer indexes `.claude/` (via `modulePathIgnorePatterns`). A leftover agent worktree under `.claude/worktrees/` duplicated the manual mocks in `tests/__mocks__/` and made every jest run emit a `jest-haste-map: duplicate manual mock found` warning; test files in worktrees were already excluded, but module indexing was not. Verified warning-free with a worktree present.
- **BREAKING — package**: The package is now published as the scoped **`@deepl/cli`** (previously the unpublished working name `deepl-cli`). Scoped packages default to restricted visibility, so `publishConfig.access: "public"` is set explicitly — without it the publish fails. The `bin` name is unchanged: the command is still `deepl`, and scoping changes only the install string (`npm install -g @deepl/cli`). Repository, bugs, and homepage metadata now point at `github.com/DeepL/deepl-cli` directly instead of relying on the redirect from the legacy `DeepLcom` org name.
- **BREAKING — cache/runtime**: The translation cache now uses Node's built-in `node:sqlite` module instead of the `better-sqlite3` native addon, and the CLI consequently requires **Node.js >= 24** (`engines.node` is now `>=24.0.0`). Node 24 is the first release where `node:sqlite` is non-experimental; Node 18/20 lack the module entirely and Node 22 would both warn on every invocation and downgrade the bundled SQLite (3.50.4 vs 3.53.1). Existing cache databases are read in place with no migration — the on-disk format is unchanged (SQLite 3.53.2-written files verified readable, WAL mode and `user_version` stamp included). **Migration**: upgrade to Node 24 (current LTS), e.g. `nvm install 24`; no other action is needed, and the cache keeps its contents.
Expand All @@ -23,6 +24,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **deps**: `commander` 14.0.3 → 15.0.0. commander 15 is ESM-only (`"type": "module"`) and requires Node >=22.12.0, so it was unmergeable until the Node 24 baseline landed. Jest's `transformIgnorePatterns` allowlist gains `commander` so ts-jest transforms it under CommonJS test execution; without that, 28 suites fail to load with `SyntaxError: Cannot use import statement outside a module`.
- **ci**: Test matrix, release workflow, and security workflow now target Node 24 (previously Node 20 and 22). Node 20 reached end-of-life in April 2026, and Node 24 is the current LTS. This aligns CI with the runtime the project is moving to; the `engines.node` range is unchanged in this entry and is bumped separately.

### Fixed

- **hooks**: Generated git hooks no longer emit a broken install instruction. The `pre-push` hook template told users to globally install the unpublished `deepl-cli` name — which fails with `ENOVERSIONS` — and now points at `@deepl/cli`. Reported by **@maa-xx** in #70, who correctly diagnosed that the documentation instructed readers to install a package that does not resolve; their docs fix was superseded by actually publishing the package, but this source-level occurrence was the one their PR missed and is now guarded by a regression test asserting generated hook output never references an unpublished package name.

### Removed

- **deps**: `better-sqlite3` and `@types/better-sqlite3`. The production dependency tree no longer contains any native addon, removing the entire class of ABI-mismatch failures (`ERR_DLOPEN_FAILED` / `NODE_MODULE_VERSION` errors after a Node major upgrade, e.g. via `brew upgrade node`), a 1.9 MB platform-specific binary, and the C++ compilation-toolchain requirement for installs from source. The cacheless-degradation safety net remains: a runtime whose `node:sqlite` is missing (Node < 22.5.0) warns once and runs uncached rather than crashing, and never touches the cache database.
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ project maintainer.

## Prerequisites

- **Node.js** >= 20.0.0
- **Node.js** >= 24.0.0
- **npm** >= 9.0.0
- A [DeepL API key](https://www.deepl.com/pro-api) (free tier works for development)

## Getting Started

```bash
# Clone the repository
git clone https://github.com/DeepLcom/deepl-cli.git
git clone https://github.com/DeepL/deepl-cli.git
cd deepl-cli

# Install dependencies
Expand Down Expand Up @@ -228,4 +228,4 @@ When filing a bug report, include:
- [docs/API.md](./docs/API.md) -- Complete CLI command reference
- [DeepL API Docs](https://www.deepl.com/docs-api) -- Official API documentation

[issues]: https://github.com/DeepLcom/deepl-cli/issues
[issues]: https://github.com/DeepL/deepl-cli/issues
40 changes: 24 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> A next-generation command-line interface for DeepL translation and writing enhancement

[![CI](https://github.com/DeepLcom/deepl-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepLcom/deepl-cli/actions/workflows/ci.yml)
[![CI](https://github.com/DeepL/deepl-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepL/deepl-cli/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)

**DeepL CLI** is a comprehensive, developer-friendly command-line tool that integrates DeepL's powerful translation API and cutting-edge Write API for grammar and style enhancement. Built with TypeScript and designed for modern development workflows.
Expand Down Expand Up @@ -53,11 +53,32 @@ For security policy and vulnerability reporting, see [SECURITY.md](SECURITY.md).

## 📦 Installation

> **Prerequisite:** Node.js **24 or later** (except for Homebrew, which installs Node for you). The cache uses Node's built-in [`node:sqlite`](https://nodejs.org/api/sqlite.html) module — no native compilation, no build toolchain needed.

### Homebrew (macOS / Linux)

```bash
brew install deepl/tap/deepl
```

Installs the `deepl` command and everything it needs, including Node.

### npm

```bash
npm install -g @deepl/cli

# Verify installation
deepl --version
```

The package is scoped, but the command is just `deepl`.

### From Source

```bash
# Clone the repository
git clone https://github.com/DeepLcom/deepl-cli.git
git clone https://github.com/DeepL/deepl-cli.git
cd deepl-cli

# Install dependencies
Expand All @@ -71,21 +92,8 @@ npm link

# Verify installation
deepl --version
# Output: deepl-cli 1.x.x
```

> **Note:** This project uses [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3) for local caching, which requires native compilation. If `npm install` fails with build errors, ensure you have:
>
> - **macOS**: Xcode Command Line Tools (`xcode-select --install`)
> - **Linux**: `python3`, `make`, and `gcc` (`apt install python3 make gcc g++`)
> - **Windows**: Visual Studio Build Tools or `windows-build-tools` (`npm install -g windows-build-tools`)

### From npm (not yet published)

An npm package is not yet published; install from source until then.

> **CI examples below** (and generated hook output) assume a published npm package; source-installed users should substitute the source-install path.

## 🚀 Quick Start

### 1. Get Your DeepL API Key
Expand Down Expand Up @@ -1331,7 +1339,7 @@ Cache location: `~/.cache/deepl-cli/cache.db` (or `~/.deepl-cli/cache.db` for le

```bash
# Clone repository
git clone https://github.com/DeepLcom/deepl-cli.git
git clone https://github.com/DeepL/deepl-cli.git
cd deepl-cli

# Install dependencies
Expand Down
7 changes: 4 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

| Version | Supported |
|---------|--------------------|
| 1.1.x | :white_check_mark: |
| 1.0.x | :white_check_mark: |
| < 1.0 | :x: |
| 2.x | :white_check_mark: |
| < 2.0 | :x: |

Versions before 2.0.0 were never published to a package registry (source installs only) and are not supported.

## Reporting a Vulnerability

Expand Down
6 changes: 3 additions & 3 deletions docs/SYNC.md
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g deepl-cli
- run: npm install -g @deepl/cli
- name: Check translations are up to date
run: deepl sync --frozen
env:
Expand All @@ -832,7 +832,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g deepl-cli
- run: npm install -g @deepl/cli
- name: Sync and commit translations
run: |
git config user.name "github-actions[bot]"
Expand Down Expand Up @@ -863,7 +863,7 @@ i18n-check:
stage: test
image: node:20
script:
- npm install -g deepl-cli
- npm install -g @deepl/cli
- deepl sync --frozen
variables:
DEEPL_API_KEY: $DEEPL_API_KEY
Expand Down
16 changes: 5 additions & 11 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -417,19 +417,13 @@ rm ~/.cache/deepl-cli/cache.db # or ~/.deepl-cli/cache.db for legacy installat
deepl cache enable
```

### "Translation cache backend failed to load" with NODE_MODULE_VERSION mismatch
### "Translation cache backend failed to load"

**Cause:** The `better-sqlite3` native addon was compiled for a different Node.js version than the one currently running. This happens when you switch Node.js versions (e.g., via `nvm use`, `fnm`, or a system upgrade) without rebuilding native modules.
**Cause:** The cache uses Node's built-in `node:sqlite` module, which requires Node.js 24 or later (the CLI's minimum supported version). On an older runtime the module doesn't exist, so caching cannot start.

Translation and write commands keep working with caching disabled for the run; your cache database is not modified. `deepl cache` subcommands fail until the backend loads again.
Translation and write commands keep working with caching disabled for the run; your cache database is not modified. `deepl cache` subcommands fail until the CLI runs on a supported Node.js version.

**Solution:**

```bash
npm rebuild better-sqlite3
```

or reinstall the CLI / switch back to the Node.js version it was installed with.
**Solution:** run the CLI with Node.js 24+ (e.g. `nvm install 24 && nvm use 24`), or install via Homebrew (`brew install deepl/tap/deepl`), which manages Node for you.

---

Expand Down Expand Up @@ -534,7 +528,7 @@ If you encounter an issue not covered here, check the [DeepL API documentation](

## Still Having Issues?

If your problem isn't listed above, [file a bug report](https://github.com/DeepLcom/deepl-cli/issues/new) with:
If your problem isn't listed above, [file a bug report](https://github.com/DeepL/deepl-cli/issues/new) with:

- The command you ran
- The full error output
Expand Down
2 changes: 1 addition & 1 deletion examples/05-document-translation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Key Features:
- Real-time file watching

Installation:
npm install -g deepl-cli
npm install -g @deepl/cli

Usage:
deepl translate "Hello, world!" --to es
Expand Down
2 changes: 1 addition & 1 deletion examples/18-cicd-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ jobs:
node-version: '20'

- name: Install DeepL CLI
run: npm install -g deepl-cli
run: npm install -g @deepl/cli

- name: Configure API Key
env:
Expand Down
6 changes: 3 additions & 3 deletions examples/31-sync-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ cat << 'WORKFLOW'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g deepl-cli
- run: npm install -g @deepl/cli
- name: Check translations are up to date
run: deepl sync --frozen
env:
Expand All @@ -133,7 +133,7 @@ cat << 'GITLAB'
stage: test
image: node:20
script:
- npm install -g deepl-cli
- npm install -g @deepl/cli
- deepl sync --frozen
variables:
DEEPL_API_KEY: $DEEPL_API_KEY
Expand All @@ -158,7 +158,7 @@ cat << 'AUTOSYNC'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g deepl-cli
- run: npm install -g @deepl/cli
- name: Sync translations
run: deepl sync --format json
env:
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ This directory contains practical, real-world examples of using the DeepL CLI.

All examples assume you have:

1. Installed DeepL CLI (`npm install -g deepl-cli` or `npm link`)
1. Installed DeepL CLI (`npm install -g @deepl/cli` or `npm link`)
2. A DeepL API key configured (`deepl auth set-key YOUR_API_KEY`)

## Running Examples
Expand Down
2 changes: 1 addition & 1 deletion src/services/git-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ echo "🔍 Validating all translations before push..."
# Check if deepl CLI is available
if ! command -v deepl &> /dev/null; then
echo "⚠️ DeepL CLI not found in PATH"
echo " Install: npm install -g deepl-cli"
echo " Install: npm install -g @deepl/cli"
exit 0
fi

Expand Down
19 changes: 19 additions & 0 deletions tests/unit/services/git-hooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ describe('GitHooksService', () => {
});
});

describe('generated hook content', () => {
// Regression guard for the class of bug reported in PR #70: docs pointed
// at the unpublished `deepl-cli` npm name, and the fix missed this file —
// so the CLI itself kept emitting a broken install instruction into
// generated hooks. Generated output must only ever name the published
// package, @deepl/cli.
const hookTypes = ['pre-commit', 'pre-push', 'commit-msg', 'post-commit'] as const;

it.each(hookTypes)('%s output never references an unpublished package name', (hookType) => {
gitHooksService.install(hookType);

const content = fs.readFileSync(path.join(testHooksDir, hookType), 'utf-8');
expect(content).not.toMatch(/install\s+-g\s+deepl-cli\b/);
if (/npm install/.test(content)) {
expect(content).toContain('npm install -g @deepl/cli');
}
});
});

describe('install()', () => {
it('should install pre-commit hook', () => {
gitHooksService.install('pre-commit');
Expand Down