Tokenless Windows integration
This reference documents the Windows adapter's host contract and path lookup for maintainers. For installation and daily use, see the QwenWork user guide.
QwenWork host contract
QwenWorkCN 1.3.2-26101704 supplies
QWENWORK_PLUGIN_HOOK_COMPATIBILITY=managed-tool-hooks-v1 through the env
entries for opencode and qwencode in
resources/agent-sdk/engine-runtime-manifest.json inside its installation.
This identifies Bash events that execute in Windows PowerShell. The adapter
reads the host value; the installer must not force it, because legacy Qoder CLI
sessions use Git Bash and need POSIX rewriting when the flag is absent.
Windows installation sets each command hook's shell to powershell.
In the same QwenWorkCN version, the installed
resources/agent-sdk/opencode/qoderwork-plugin-adapter.mjs passes
configuration.shell ?? true to Node's spawn. This is the host code that
selects PowerShell for the Python hook command; the manifest flag above instead
identifies the shell used by the tool. Hosts that ignore shell are unverified:
the generated command uses PowerShell syntax and cannot run under cmd.exe.
The verified host ignores ordinary hook execution failures and leaves the tool
input unchanged; exit code 2 is reserved for blocking decisions. A missing
Python interpreter or shared hook resource therefore disables optimization for
that invocation without requiring another dispatcher.
PreTool matches Bash, PowerShell, mcp__workspace__bash, and
mcp__qw-builtin__mcp_workspace_bash; RTK decides whether to rewrite each command.
PowerShell calls bind the native RTK executable and scope attribution variables
to that invocation. PostTool classifies PowerShell output as command output,
retains file-content protection, and avoids compressing RTK output twice.
Unsupported commands pass through.
The PowerShell wrapper uses a child-scope rtk alias. In a rewritten compound
command, this also binds any pre-existing bare rtk invocation to the managed
binary; POSIX binding only changes calls inserted by the rewrite. Explicit
executable paths are unaffected. The wrapper preserves $? and $LASTEXITCODE
after restoring attribution variables, including nonzero native exits, without
adding stderr output or entries to $Error.
When this wrapper is the final command passed to powershell -Command or
pwsh -Command, a $false value of $? produces process exit code 1; the original
native exit code remains available in the session's $LASTEXITCODE.
The lifecycle script searches %LOCALAPPDATA%/Programs/QwenWorkCN, including
version subdirectories. TOKENLESS_QWENWORK_APP overrides the installation
directory; TOKENLESS_QWENWORK_HOME overrides the data directory
(default ~/.qwenworkcn). The plugin is copied to plugins-custom/tokenless,
and hooks record the Python interpreter's absolute path. Installation does not
change settings or enable disabled plugins. Modified or foreign plugins are
not overwritten or removed. The desktop application needs the npm command
directory on its PATH.
Native hook tests cover rewriting, execution, compression, file-read protection, statistics, deduplication, and lifecycle operations. The optional installed-host tests read both engines' manifest environments and invoke the installed OpenCode adapter to verify hook shell selection, rewriting, PostTool, Read protection, statistics, and fail-open after a shared resource is removed. These tests do not establish that a particular application session has loaded or enabled the plugin; check that separately in a QwenWork local session.
Binary discovery and support boundaries
Native binary discovery uses the executable's sibling directory and absolute
PATH entries. Unlike Unix, Windows discovery does not check file or directory
ACLs, ownership, or reparse points: configured installation and PATH directories
are trusted. RTK resolution accepts only .exe; general dependency discovery
also accepts .com, .bat, and .cmd entries from PATHEXT.
Windows support covers the native CLI and QwenWork adapter. npm copies other adapter resources but skips Claude auto-enable; other Windows adapters are not validated. Security-workspace/VM sessions and Windows ARM64 are unsupported.
Build and test on Windows
Build this component from native PowerShell with Git, Rust's
x86_64-pc-windows-msvc toolchain, and Visual Studio C++ Build Tools (including
the Windows SDK). Packaging requires Node.js/npm and Python 3.10+; the
QwenWork adapter also uses Python. No Git Bash, WSL, or make is required. Windows ARM64 is not
supported. The Linux CI entry point is described below.
cd src/tokenless
./scripts/build-windows.ps1
node npm/scripts/package-npm.js --target win32-x64
$packages = Get-ChildItem npm/dist/tokenless-win32-x64/*.tgz, npm/dist/tokenless/*.tgz
npm install -g $packages.FullName
The build script fetches and patches the pinned RTK revision and writes both
executables to target/npm-prebuilt/win32-x64. Add -Debug for a development
build. The npm packages are local artifacts; this command does not publish them.
For a combined release, transfer the complete target/npm-prebuilt/win32-x64
directory from the Windows build host to the same location under src/tokenless
on the Linux packaging host. Use the same source revision on both hosts, then
run make npm-package-all after staging the other four platform directories.
--all requires all five targets and fails if any binary is missing;
--target x64 also includes Windows. Use --target linux or --target darwin
when packaging only those platforms. The Linux CI builder also produces the Windows
binaries, so a native build host is optional for artifact generation.
For local verification, run cargo fmt --all -- --check,
cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace,
and python -X utf8 -B tests/test_windows.py after packaging. Set PYO3_PYTHON
to the intended Python executable when testing the Python workspace member.
The Windows smoke suite invokes real PowerShell hooks and native executables;
application UI loading and activation require a separate QwenWork local session.
Set TOKENLESS_TEST_QWENWORK_APP to the installed version directory (containing
QwenWorkCN.exe) to test managed Bash with the actual host manifest environment
for both engines and both MCP aliases, and to exercise the installed OpenCode
hook runner using Node on PATH. Set TOKENLESS_TEST_BASH to Git Bash's executable
to include legacy execution tests. The database rejection fixtures use system
temporary storage (%SystemRoot%/Temp on Windows, /tmp on Unix), independently
of a home-backed TEMP/TMP/TMPDIR; they report unavailable fixtures if that
directory is unwritable or inside the trusted home. A separate test covers
allowed home paths. Set TOKENLESS_TEST_POWERSHELL to pwsh.exe when rerunning
the Rust powershell_binding tests and the installed-host smoke test's rewritten
tool command on PowerShell 7; their default is Windows PowerShell 5.1. The host
still executes the registered Python hooks with the installer's powershell setting.
To test installed npm launchers, set TOKENLESS_TEST_BIN to the installed
anolisa-tokenless/bin directory and TOKENLESS_TEST_NODE to the Node executable
to verify (including the supported minimum, 16.7.0).
Linux CI and release artifacts
tokenless-prebuilt-ci.yaml uses the self-hosted Linux release runner
(anolisa-release-cross-x64) to cross-compile x86_64-pc-windows-msvc and run
Wine smoke tests on pushes and manual dispatches. Pull requests run the action's
regression tests on the general CI runner. The same build action participates in the release and preview
matrices. Historical source-tag previews keep the matrix from that source tag.
The runner must already contain anolisa/rust-release-builder:windows-msvc-x86_64.
Its configuration digest is
sha256:7649bcb55d8c5632232c7f27e3c2191b71fb7c31149de87412c447fc7a997303.
Docker's containerd image store reports the corresponding manifest digest as the
image ID: sha256:1392a2684a4853a3da0219caef07c4b47f8833775b1559f18d54cd656abefb88.
Both fixed identifiers refer to the same verified builder.
The action checks that identity and the image's SDK inventory before building;
it does not build or pull the image. Provision it before enabling the job.
The frozen image contains Rust 1.93.0, cargo-xwin 0.23.1, maturin 1.15.0,
LLVM 18.1.3, Wine 9.0 and Windows Python 3.11.9 with its import libraries.
The host needs the existing release-runner tools, including Docker,
Node.js/npm and cargo-sbom 0.10.0. Source, Cargo downloads, build output and Wine
state use separate mounts; host compiler wrappers and Cargo configuration are
not passed into the container.
Run the production entry point locally from the repository root with empty output
directories. It builds the checked-out commit, or the exact --tag when supplied:
root="$PWD"
mkdir -p /tmp/tokenless-windows-release
RUSTC_WRAPPER= RUSTC_WORKSPACE_WRAPPER= \
TOKENLESS_SOURCE_WORKTREE=/tmp/tokenless-windows-release/source \
bash .github/actions/build-tokenless-prebuilt/build.sh \
--source-repo "$root" \
--output-dir /tmp/tokenless-windows-release/artifacts \
--wheel-output-dir /tmp/tokenless-windows-release/wheels \
--version 0.9.0 --target-os windows --target-arch x86_64 \
--profile windows-msvc-x86_64
The Windows ZIP contains tokenless.exe, rtk.exe, LICENSE and two npm
tarballs under npm/ (the Windows-targeted root package and win32-x64 platform
package). It has SHA-256 and CycloneDX sidecars like the other release archives.
CLI and RTK use a static CRT, with an import check rejecting external VC++ runtime
DLLs. The separate Python wheel uses cp311-abi3-win_amd64 and the runtime supplied
with Windows Python. The release workflow uploads
these assets to GitHub; it does not publish to npm or PyPI. Use all five platform
packages when preparing a combined npm registry release, rather than publishing
the Windows-only root tarball as the cross-platform package. Repeated builds currently
differ in PE build identifiers; the checksums identify the specific generated
files, and byte-for-byte reproduction is not guaranteed.
Wine smoke tests extract the ZIP and wheel into a path containing spaces and
Chinese characters, then exercise the CLI, RTK, SDK, compression, byte-exact
Stash recovery, denied retrieval and statistics attribution. npm metadata and
embedded binaries are also checked. Smoke execution has no network access and
an outer timeout. Compiler and Wine failures fail the job. Builder diagnostics
remain in <output-dir>.build/out; the CI job uploads those diagnostics.
Wine does not validate native Windows ACL behavior, PowerShell hooks, Node
launchers or QwenWork activation. Continue running the native test suite above
on Windows 10 and Windows 11 for those acceptance checks.