monitor-with-permissions

Windows only

Like upload-folder-with-permissions, this command only runs on the Windows build of the CLI.

Continuous version of upload-folder-with-permissions. Performs the initial permissioned sync, then keeps watching the folder and re-syncing — both file content and ACL changes — until you stop the process.

Syntax

Usage: curiosity-cli monitor-with-permissions --server <url> --token <token> --path <dir> --permissions-cache <file> --fetch-server-state <bool> [options]

curiosity-cli monitor-with-permissions \
  --server             https://my-workspace.example.com/ \
  --token              $CURIOSITY_TOKEN \
  --path               \\\\fileserver\\Shared \
  --permissions-cache  C:\\curiosity\\acl-cache.json \
  --fetch-server-state true

Options

Same set as monitor, plus:

Option Description
--permissions-cache Path to a .json file used to cache resolved ACL → user/group mappings between runs. Alias -c. Required.

As with the one-shot variant:

  • --upload-to is forced to Custom.
  • The CLI invokes graph.MapPermissionsAsync for new/changed files and graph.CheckPermissionsChanged to re-evaluate ACLs on files that already exist in the graph.
On a network share, schedule the one-shot command instead

Like monitor, this command does one full pass and then relies on file-system change notifications — dependable on a local disk, best-effort over SMB, and absent entirely on an NFS mount. A watcher that stops because the session dropped is not re-created, and nothing re-reads the tree afterwards, so the workspace drifts without anything being logged. For a network share, schedule upload-folder-with-permissions instead: it re-walks the tree every run. See Why the watcher is unreliable over SMB and Running a sync on a schedule.

Running it as a service

The same systemd / NSSM / Windows Service pattern from monitor applies — wrap the command in your platform's service supervisor so it restarts on failure and starts on boot. Because this command only runs on Windows, the supervisor is NSSM or sc.exe, and the question is which account the service runs as.

Run the service as a gMSA

A Group Managed Service Account (gMSA) is a domain account whose password Active Directory generates and rotates itself. Running the connector as a gMSA gives it a domain identity to read the share and, for the -with-permissions variants, to resolve the NTFS ACL SIDs against Active Directory — without the --username / --password / --domain impersonation flags, so no domain credential appears in the service configuration at all.

Create the account in Active Directory and install it on the host first: Running as a gMSA on the Workspace deployment docs covers the KDS root key, New-ADServiceAccount, Install-ADServiceAccount and Test-ADServiceAccount. The steps below assume Test-ADServiceAccount returns True for CORP\svc-curiosity$.

1

Put the CLI machine-wide

Download curiosity-cli.exe from the releases page and save it to a fixed path every account can read — E:\CuriosityCLI\curiosity-cli.exe below. It is self-contained, so the host needs no .NET SDK and no .NET runtime.

Don't install the CLI as a dotnet tool here. dotnet tool install --global installs into the invoking user's profile (%USERPROFILE%\.dotnet\tools), which the gMSA cannot see, and a dotnet-tool install gives you a launcher that runs the tool through dotnet rather than the standalone curiosity-cli.exe that NSSM and sc.exe need to point at. See Running under a service account.

Keep the whole path free of spaces

A service command line registered through sc.exe or NSSM is stored unquoted, so a path such as C:\Program Files\... registers fine and then fails when the service starts. Use a path like E:\CuriosityCLI instead.

2

Grant the gMSA access

Resource Access Notes
The monitored share (e.g. \\fileserver\Shared) Read Both the share permission and the NTFS permission must allow the gMSA (effective access is the more restrictive of the two). Grant read on the whole tree you want indexed.
--permissions-cache file location (e.g. E:\CuriosityCLI\acl-cache.json) Modify Keep the path stable across runs.
Active Directory read Default Resolving ACL SIDs to users/groups only needs standard authenticated-user read access to the directory — no extra grants in a default AD.

The account also needs the Log on as a service right (secpol.msc → Local Policies → User Rights Assignment). NSSM grants it when it sets the account; sc.exe does not on all Windows versions.

3

Create the service

With NSSM:

nssm install CuriosityMonitor "E:\CuriosityCLI\curiosity-cli.exe"
nssm set CuriosityMonitor AppParameters monitor-with-permissions ^
--server https://my-workspace.example.com/ ^
--token  %CURIOSITY_TOKEN% ^
--path   \\fileserver\Shared ^
--permissions-cache E:\CuriosityCLI\acl-cache.json ^
--fetch-server-state true
nssm set CuriosityMonitor AppEnvironmentExtra CURIOSITY_TOKEN=<library-token>
nssm set CuriosityMonitor ObjectName CORP\svc-curiosity$ ""
nssm start CuriosityMonitor

ObjectName CORP\svc-curiosity$ "" is the gMSA equivalent of an account + password pair — the account name ends in $ and the empty string is the password; Windows fetches the managed password from Active Directory itself. With plain sc.exe the same is sc.exe config CuriosityMonitor obj= "CORP\svc-curiosity$" password= "".

Token handling under a gMSA

The service needs a workspace Library Token (create one under Manage → Tokens → Library, ideally for a dedicated service user with minimal rights). Two ways to provide it:

  • Environment variable in the service definition (shown above with AppEnvironmentExtra) — simplest; the token lives only in the service configuration, readable by administrators.

  • store-token + --token auto — the encrypted token file is written to the running user's %APPDATA%, so it must be created as the gMSA. A gMSA cannot log on interactively; run the one-off command through a scheduled task instead:

    $a = New-ScheduledTaskAction -Execute "E:\CuriosityCLI\curiosity-cli.exe" `
          -Argument "store-token -s https://my-workspace.example.com/ -t <library-token>"
    $p = New-ScheduledTaskPrincipal -UserId "CORP\svc-curiosity$" -LogonType Password
    Register-ScheduledTask -TaskName "curiosity-store-token" -Action $a -Principal $p
    Start-ScheduledTask    -TaskName "curiosity-store-token"
    Unregister-ScheduledTask -TaskName "curiosity-store-token" -Confirm:$false
    

    Afterwards the service can use --token auto and no token appears in the service definition. (-LogonType Password is correct for gMSAs — Windows fetches the managed password itself.)

Troubleshooting

Symptom Likely cause
Service fails to start with error 1069 (logon failure) Missing trailing $ in the account name, a non-empty password was configured, or the account lacks the Log on as a service right.
Test-ADServiceAccount returns False The host cannot retrieve the managed password — see gMSA troubleshooting.
Access is denied reading the share Check both the share permission and the NTFS ACL for the gMSA; also confirm the share path is a UNC path, not a drive letter mapped for another user (drive mappings are per-logon and invisible to the service).
Can't find token for url with --token auto The token was stored under a different account's %APPDATA% — re-run store-token as the gMSA (see above) or pass the token explicitly.
ACL sync produces no permissions Confirm you run the Windows build of the CLI and the -with-permissions command variant; the non-Windows builds do not support permission sync.

Remarks

  • Use this command on Windows to keep a folder's content and its Active Directory ACLs continuously in sync with the workspace; for a single pass use upload-folder-with-permissions.
  • It runs only on the Windows build of the CLI and forces --upload-to Custom.
  • The process runs until stopped — wrap it in a service supervisor (NSSM, Windows Service) for production, and keep the --permissions-cache path stable across runs.

See also

© 2026 Curiosity. All rights reserved.