> For the complete documentation index, see [llms.txt](https://newdocs.keeper.io/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://newdocs.keeper.io/en/keeperpam/commander-sdk/keeper-commander-sdks/sdk-command-reference/nested-shared-folder-commands.md).

# Nested Shared Folder Commands

With the introduction of **Nested Shared Folders with Role-Based Folder Permissions**, we’ve rebuilt the vault’s folder, sharing and permissions model from the ground up, delivering a more flexible and scalable experience for every user and team.

### List command

List Nested shared folders and records cached locally. By default, both folders and records are shown. Use the `--folders` or `--records` flag to filter, and `--format` to control the output style.

<details>

<summary>DotNet CLI</summary>

**Command**: `nsf-list`

**Parameters**:

| Parameter   | Description                                        |
| ----------- | -------------------------------------------------- |
| `--folders` | Show only folders                                  |
| `--records` | Show only records                                  |
| `--format`  | Output format: `table` (default), `csv`, or `json` |
| `--output`  | Path to output file. Ignored for `table` format    |

**Examples**:

{% code expandable="true" %}

```bash
My Vault> nsf-list

=== Keeper NSF Summary ===
  Folders: 1
  Records: 1

--- Folders ---
FolderUid               Name                   ParentUid               Subfolders  Records
----------------------  ---------------------  ----------------------  ----------  -------
F1lX8kCMx--W0ndcmeaX6w  Child-folder           eRcyzWqxQhMlieLuRq29nA  0           0      

--- Records ---
RecordUid               Name          Type   Revision  Version  Shared  FileSize  ThumbnailSize
----------------------  ------------  -----  --------  -------  ------  --------  -------------
LTVdDDvuSKLmWYiNbKjrYg  Notes1234     login  5017162   3        False   0         0

```

{% endcode %}

</details>

<details>

<summary>DotNet SDK</summary>

**Function:**

```csharp
var vault = new VaultOnline(auth);
await vault.SyncDown();
Console.WriteLine($"Folders: {vault.KeeperNSFFolderCount}, Records: {vault.KeeperNSFRecordCount}");
foreach (var folder in vault.KeeperNSFFolderNodes)
{
    Console.WriteLine($"[Folder] {folder.FolderUid}  {folder.Name}");
}
foreach (var record in vault.KeeperNSFRecordEntries)
{
    Console.WriteLine($"[Record] {record.RecordUid}  {record.Name}  v{record.Version}");
}
if (vault.TryGetKeeperNSFFolder("folderUid1", out var f))
{
    Console.WriteLine($"Found folder: {f.Name}");
}
if (vault.TryResolveKeeperNSFRecord("MyLogin", out var r))
{
    Console.WriteLine($"Resolved record: {r.RecordUid}");
}
```

</details>

<details>

<summary>Power Commander</summary>

**Command**: `Get-KeeperNSFList`

**Alias**: `nsf-list`

**Parameters**:

| Parameter  | Description                                        |
| ---------- | -------------------------------------------------- |
| `-Folders` | Show only folders                                  |
| `-Records` | Show only records                                  |
| `-Format`  | Output format: `table` (default), `csv`, or `json` |
| `-Output`  | Path to output file. Ignored for `table` format    |

**Examples**:

{% code expandable="true" %}

```
PS > Get-KeeperNSFList
PS > nsf-list -Folders
PS > nsf-list -Records -Format json -Output nsf-records.json
PS > nsf-list -Format csv -Output nsf.csv
```

{% endcode %}

</details>

<details>

<summary>Python CLI</summary>

**Command:** `nsf-list`

**Parameters**:\
`--folders` Show only folders\
`--records` Show only records\
`--format` {table,csv,json}\
`--output` OUTPUT Path to output file (ignored for table format)

**Example:**

```shellscript
My Vault> nsf-list
  #  Item type    UID                     Title                                      Type                     Description
---  -----------  ----------------------  -----------------------------------------  -----------------------  -------------
  1  Folder       <folder_uid>            Folder Title
  2  Record       <record_uid>            new test nsf                               login
```

</details>

<details>

<summary>Python SDK</summary>

**Function :** `list_nsf_items`

```python
    INCLUDE_FOLDERS = True
    INCLUDE_RECORDS = True

    rows = nsf_management.list_nsf_items(
        vault,
        include_folders=INCLUDE_FOLDERS,
        include_records=INCLUDE_RECORDS,
    )
    if not rows:
        print("No NSF folders or records found. Run sync-down first.")
        return
    print(f"{'Type':<8} {'UID':<28} {'Title':<30} {'Record Type':<15} {'Location'}")
    print("-" * 100)
    for row in rows:
        print(
            f"{row.item_type:<8} {row.uid:<28} {row.title[:28]:<30} "
            f"{(row.record_type or '')[:15]:<15}"
        )
    print(f"\nTotal items: {len(rows)}")
```

</details>

### Get command

Retrieves detailed information about a specific Keeper NSF record or folder by UID or name. Shows metadata, user permissions, and share administrators.

<details>

<summary>DotNet CLI</summary>

**Command**: `nsf-get`

**Parameters**:

| Parameter  | Description                                                                         |
| ---------- | ----------------------------------------------------------------------------------- |
| `--uid`    | Record or folder UID to look up                                                     |
| `--name`   | Record or folder name to search for (case-insensitive; falls back to partial match) |
| `--format` | Output format: `detail` (default) or `json`                                         |

**Examples**:

{% code expandable="true" %}

```bash
MyVault> nsf-get --uid GS3J1s9ARg1-P5LRQOeRTA

                  UID: GS3J1s9ARg1-P5LRQOeRTA
                 Type: login
                Title: Record-Share
             Password: ********
           Folder UID: AAAAAAAAAAAAAAAAAALjjA
          Folder Name: (unknown)
          Folder Path:
          
          User Permissions:

                 User: example1@keepersecurity.com
                Owner: Yes
            Shareable: Yes
            Read-Only: No

                 User: example2@keepersecurity.com
                 Role: full-manager
            Shareable: Yes
            Read-Only: No

                 User: example3@keepersecurity.com
                 Role: viewer
            Shareable: No
            Read-Only: Yes

Share Admins (5, showing first 2):
  example4@keepersecurity.com
  example5@keepersecurity.com
  ... and 3 more
```

{% endcode %}

</details>

<details>

<summary>DotNet SDK</summary>

**Function:**

```csharp
var vault = new VaultOnline(auth);
await vault.SyncDown();
if (vault.TryGetKeeperNSFRecord(recordUid, out var record))
{
    Console.WriteLine($"Record: {record.RecordUid} ({record.Name}) v{record.Version}");
    foreach (var access in vault.Storage.KdRecordAccesses.GetLinksForSubject(record.RecordUid))
    {
        Console.WriteLine($"  user-uid={access.AccessTypeUid}  owner={access.Owner}  " +
                          $"edit={access.CanEdit}  view={access.CanView}  delete={access.CanDelete}");
    }
}
if (vault.TryResolveKeeperNSFFolder(folderUidOrName, out var folder))
{
    var stored = vault.Storage.KdFolders.GetEntity(folder.FolderUid);
    Console.WriteLine($"Folder: {folder.FolderUid} ({folder.Name})  owner={stored?.OwnerUsername}");
}
```

</details>

<details>

<summary>Power Commander</summary>

**Command**: `Get-KeeperNSFRecord`

**Alias**: `nsf-get`

**Parameters**:

| Parameter | Description                                                                         |
| --------- | ----------------------------------------------------------------------------------- |
| `-Uid`    | Record or folder UID to look up                                                     |
| `-Name`   | Record or folder name to search for (case-insensitive; falls back to partial match) |
| `-Format` | Output format: `detail` (default) or `json`                                         |

**Examples**:

{% code expandable="true" %}

```ps1
PS > nsf-get oqf7DOKZvSYuwhwFc6qvOw
                                                   
                  UID: oqf7DOKZvSYuwhyqtewFc6qvOw
                 Type: databaseCredentials
                Title: 1234
             Password: ********
                 Host: hostName: 1.2.3.4, port: 1234
           Folder UID: wbxwceZdbqhusyPVcyuR-7IybjA
          Folder Name: QWE-test
          Folder Path: /QWE-test

     User Permissions:

                 User: example1@keepersecurity.com
                Owner: Yes
            Shareable: Yes
            Read-Only: No

                 User: example2@keepersecurity.com
                 Role: full-manager
            Shareable: Yes
            Read-Only: No

                 User: example3@keepersecurity.com
                 Role: viewer
            Shareable: No
            Read-Only: Yes


Share Admins (5, showing first 2):
  example4@keepersecurity.com
  example5@keepersecurity.com
  ... and 3 more
```

{% endcode %}

</details>

<details>

<summary>Python CLI</summary>

**Command:** `nsf-get`

Parameters:

`uid` Record UID, folder UID, or title\
`--format` {detail, json} Output format: detail (default) or json\
`--verbose, -v` Show full permission breakdown for each accessor\
`--unmask` Reveal masked field values (passwords, secrets)

Example:

```shellscript
My Vault> nsf-get <record_uid>

                 UID: <record_uid>
                Type: pamNetworkConfiguration
               Title: Test Configuration
              Folder: Folder - Users
        Pamresources: controllerUid: <controller_uid>, folderUid: <folder_uid>

User Permissions:

  User: email@keepersecurity.com
  Owner: Yes
  Shareable: Yes
  Read-Only: No
```

</details>

<details>

<summary>Python SDK</summary>

**Function :** `get_nsf_item`

```python
    ITEM_UID_OR_TITLE = "<record_uid_or_title>"  # Record/folder UID or title

    detail = nsf_management.get_nsf_item(vault, ITEM_UID_OR_TITLE)
    print(json.dumps(detail, indent=2, default=str))
```

</details>

### Shortcut command

Scans all Keeper NSF folder-record links and reports records that exist in two or more folders. Optionally filters by a specific record (UID/title) or folder (UID/name).

<details>

<summary>DotNet CLI</summary>

**Command**: `nsf-shortcut-list`

**Parameters**:

| Parameter    | Description                                                                     |
| ------------ | ------------------------------------------------------------------------------- |
| `position 0` | Optional record UID, record title, folder UID, or folder name to filter results |
| `-Format`    | Output format: `table` (default), `csv`, or `json`                              |
| `-Output`    | Path to output file. Ignored for `table` format                                 |

**Examples**:

{% code expandable="true" %}

```bash
My Vault> nsf-shortcut-list
No shortcut records found.
```

{% endcode %}

**Command**: `nsf-shortcut-keep`

**Description**: For a record that appears in multiple Keeper NSF folders, keeps it in the specified folder and unlinks it from all others.

**Parameters**:

| Parameter    | Description                                                |
| ------------ | ---------------------------------------------------------- |
| `position 0` | Record UID or title of the record (required)               |
| `position 1` | Folder UID or folder name to keep the record in (required) |
| `--force`    | Skip the confirmation prompt                               |

</details>

<details>

<summary>DotNet SDK</summary>

**Function:**

```csharp
var vault = new VaultOnline(auth);
await vault.SyncDown();

foreach (var entry in vault.GetKeeperNSFShortcuts())
{
    Console.WriteLine($"{entry.RecordUid}  {entry.Title}  [{entry.Folders.Count} folders]");
    foreach (var f in entry.Folders)
    {
        Console.WriteLine($"  - {f.Name} ({f.FolderUid})");
    }
}

var keepResult = await vault.KeepKeeperNSFRecordInFolder(recordUid, keepFolderUid);
foreach (var removal in keepResult.Removals)
{
    Console.WriteLine($"{(removal.Success ? "[OK]" : "[FAIL]")} {removal.FolderName} ({removal.FolderUid})");
}
```

</details>

<details>

<summary>Power Commander</summary>

**Command**: `Get-KeeperNSFShortcut`

**Alias**: `nsf-shortcut-list`

**Parameters**:

| Parameter | Description                                                                     |
| --------- | ------------------------------------------------------------------------------- |
| `-Target` | Optional record UID, record title, folder UID, or folder name to filter results |
| `-Format` | Output format: `table` (default), `csv`, or `json`                              |
| `-Output` | Path to output file. Ignored for `table` format                                 |

**Examples**:

{% code overflow="wrap" expandable="true" %}

```powershell
PS > Get-KeeperNSFShortcut                    
No shortcut records found.
```

{% endcode %}

**Command**: `Set-KeeperNSFShortcutKeep`

**Alias**: `nsf-shortcut-keep`

**Description**: For a record that appears in multiple Keeper NSF folders, keeps it in the specified folder and unlinks it from all others.

**Parameters**:

| Parameter    | Description                                                |
| ------------ | ---------------------------------------------------------- |
| `-RecordUid` | Record UID or title of the record (required)               |
| `-FolderUid` | Folder UID or folder name to keep the record in (required) |
| `-Force`     | Skip the confirmation prompt                               |

**Examples**:

{% code overflow="wrap" expandable="true" %}

```ps1
PS > Set-KeeperNSFShortcutKeep -RecordUid <RECORD_UID> -FolderUid <FOLDER_UID>
PS > nsf-shortcut-keep <RECORD_TITLE> <FOLDER_NAME> -Force
```

{% endcode %}

</details>

<details>

<summary>Python CLI</summary>

**Command:** `nsf-shortcut`

**Parameters**:

`target` record UID or title

`folder` folder to keep (default: current)

`-f, --force` Skip confirmation prompt

**Example**:

```shellscript
My Vault> nsf-shortcut keep <record_uid> <folder_uid>
Will keep record in <record_uid> and remove from 1 other folder(s).
Do you want to proceed? [y/n]: y
Removed record from 1 folder link(s).
My Vault>
```

</details>

<details>

<summary>Python SDK</summary>

**Function :** `list_nsf_shortcuts & keep_nsf_shortcut_in_folder`

```python
##### NSF SHORTCUT LIST
    TARGET_FILTER = None  # Optional record or folder filter

    rows = nsf_folder_records.list_nsf_shortcuts(vault, target=TARGET_FILTER)
    if not rows:
        print("No NSF shortcut records found")
        return
    view = vault.nsf_data
    for row in rows:
        folder_names = []
        for fuid in row.folder_uids:
            folder = view.get_folder(fuid) if view else None
            fname = folder.name if folder and folder.name else fuid
            folder_names.append(f"{fname} ({fuid})")
        print(f"{row.record_uid} | {row.title} | {', '.join(folder_names)}")
        
        
#### NSF SHORTCUT KEEP
    RECORD_UID_OR_TITLE = "My NSF Login"
    FOLDER_UID_OR_NAME = "Projects"  # Folder to keep the record in
    FORCE = True

    shortcuts = nsf_folder_records.get_nsf_shortcut_map(vault)
    record_uid = nsf_management.resolve_nsf_record_uid(vault, RECORD_UID_OR_TITLE)
    if not record_uid:
        raise ValueError(f'Record "{RECORD_UID_OR_TITLE}" not found')
    keep_folder = nsf_management.resolve_nsf_folder_uid(vault, FOLDER_UID_OR_NAME) or FOLDER_UID_OR_NAME
    to_remove = [f for f in shortcuts.get(record_uid, set()) if f != keep_folder]
    if not to_remove:
        print("Nothing to do — record is already in only one folder.")
        return
    if not FORCE:
        answer = input(
            f"Keep record in {FOLDER_UID_OR_NAME} and remove from {len(to_remove)} folder(s)? [y/N]: "
        ).strip().lower()
        if answer not in ("y", "yes"):
            print("Aborted.")
            return
    results = nsf_folder_records.keep_nsf_shortcut_in_folder(
        vault, RECORD_UID_OR_TITLE, FOLDER_UID_OR_NAME
    )
    print(f"Removed record from {len(results)} folder link(s).")

```

</details>

### Grant/Revoke Record Permissions command

Bulk grants or revokes record-level sharing permissions for every record inside a Keeper NSF folder. Fetches current access for each record, computes the required changes, displays a plan, and applies the changes after confirmation.

<details>

<summary>DotNet CLI</summary>

**Command**: `nsf-record-permission`

**Parameters**:

| Parameter     | Description                                                                                                                                                                                      |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `position 0`  | Folder UID or name containing the records. If omitted, operates on root-level records                                                                                                            |
| `--action`    | `grant` or `revoke` (required)                                                                                                                                                                   |
| `--role`      | Access role: `viewer`, `shared-manager`, `content-manager`, `content-share-manager`, `full-manager`. Required for `grant`; for `revoke`, optionally restricts the revoke to users with that role |
| `--recursive` | Include records in subfolders                                                                                                                                                                    |
| `--force`     | Skip the confirmation prompt                                                                                                                                                                     |
| `-dry-run`    | Show what would change without applying any modifications                                                                                                                                        |

**Examples**:

{% code expandable="true" %}

```bash
My Vault> nsf-record-permission MQ8GwV3F1sQvGmXt-4zv2A --action grant --role viewer

Request to GRANT 'viewer' permission(s) in 'MQ8GwV3F1sQvGmXt-4zv2A' folder only
No permission changes are needed.
```

{% endcode %}

</details>

<details>

<summary>DotNet SDK</summary>

**Function:**

```csharp
var vault = new VaultOnline(auth);
await vault.SyncDown();

var plan = await vault.UpdateKeeperNSFRecordPermissions(
    folderUid: folderUid,
    action:    "grant",
    role:      "viewer",
    recursive: true,
    dryRun:    true);

Console.WriteLine($"Plan: {plan.Grants.Count} grants, {plan.Revokes.Count} revokes, {plan.Skipped.Count} skipped");

if (plan.Grants.Count + plan.Revokes.Count > 0)
{
    var result = await vault.UpdateKeeperNSFRecordPermissions(
        folderUid: folderUid,
        action:    "grant",
        role:      "viewer",
        recursive: true,
        dryRun:    false);

    foreach (var g in result.Grants)
    {
        Console.WriteLine($"{(g.Success ? "[OK]" : "[FAIL]")} {g.RecordUid}  {g.Email}  {g.CurrentRole} -> {g.NewRole}");
    }
}
```

</details>

<details>

<summary>Power Commander</summary>

**Command**: `Set-KeeperNSFRecordPermission`

**Alias**: `nsf-record-permission`

**Parameters**:

| Parameter    | Description                                                                                                                                                                                      |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `-FolderUid` | Folder UID or name containing the records. If omitted, operates on root-level records                                                                                                            |
| `-Action`    | `grant` or `revoke` (required)                                                                                                                                                                   |
| `-Role`      | Access role: `viewer`, `shared-manager`, `content-manager`, `content-share-manager`, `full-manager`. Required for `grant`; for `revoke`, optionally restricts the revoke to users with that role |
| `-Recursive` | Include records in subfolders                                                                                                                                                                    |
| `-Force`     | Skip the confirmation prompt                                                                                                                                                                     |
| `-DryRun`    | Show what would change without applying any modifications                                                                                                                                        |

**Examples**:

{% code overflow="wrap" expandable="true" %}

```ps1
PS > Set-KeeperNSFRecordPermission -FolderUid wbxwceZdbPVcyuR-7IybjA -Action grant -Role viewer -Recursive

Request to GRANT 'viewer' permission(s) in 'wbxwceZdbPVcyuR-7IybjA' folder recursively

  PLANNED GRANTS (1):
    oqf7DOKZvSYuwhwFc6qvOw  example1@keepersecurity.com  shared-manager -> viewer
Are you sure you want to apply the above changes? (yes/No): yes

  GRANT (1):
    [OK] oqf7DOKZvSYuwhwFc6qvOw  apohane@keepersecurity.com  shared-manager -> viewer

Summary: 1 succeeded, 0 failed, 0 skipped
```

{% endcode %}

</details>

<details>

<summary>Python CLI</summary>

**Command:** `Not implemented`

**Parameters**:

`folder` Folder UID or name

`--dry-run` Display changes without executing

`-f, --force` Skip confirmation prompts\
`-R, --recursive` Include records in subfolders\
`-a, --action` {grant, revoke}\
`-r, --role` {viewer, share-manager, content-manager, content-share-manager, full-manager}

**Example**:

```shellscript
My Vault> nsf-record-permission -a revoke <folder_uid>

REVOKE:
  <record_uid> user@keepersecurity.com content-manager
Do you want to proceed with these permission changes? [y/n]: y
revokes <record_uid> user@keepersecurity.com: ok
My Vault>
```

</details>

<details>

<summary>Python SDK</summary>

**Function :** `apply_nsf_record_permissions`

```python
    FOLDER_UID_OR_NAME = "Projects"
    ACTION = "grant"  # grant or revoke
    ROLE = "viewer"  # Required for grant
    RECURSIVE = False
    FORCE = True
    DRY_RUN = False

    plan = nsf_sharing.plan_nsf_record_permissions(
        vault,
        FOLDER_UID_OR_NAME,
        action=ACTION,
        role=ROLE,
        recursive=RECURSIVE,
        current_user=current_user,
    )
    if not plan.updates and not plan.creates and not plan.revokes:
        print("No permission changes are needed.")
        return
    for label, items in (
        ("SKIP", plan.skipped),
        ("GRANT/UPDATE", plan.updates + plan.creates),
        ("REVOKE", plan.revokes),
    ):
        if not items:
            continue
        print(f"\n{label}:")
        for item in items:
            line = f"  {item.get('record_uid')} {item.get('email', '')} {item.get('cur_role', '')}"
            if item.get("new_role"):
                line += f" -> {item['new_role']}"
            print(line)
    if DRY_RUN:
        return
    if not FORCE:
        answer = input("Proceed with permission changes? [y/N]: ").strip().lower()
        if answer not in ("y", "yes"):
            print("Aborted.")
            return
    outcomes = nsf_sharing.apply_nsf_record_permissions(vault, plan)
    for bucket, rows in outcomes.items():
        for item, result in rows:
            status = "ok" if result.get("success") else result.get("message")
            print(f"{bucket} {item.get('record_uid')} {item.get('email')}: {status}")
```

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://newdocs.keeper.io/en/keeperpam/commander-sdk/keeper-commander-sdks/sdk-command-reference/nested-shared-folder-commands.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
