splunkctl 0.12.0__tar.gz → 0.14.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. splunkctl-0.14.0/PKG-INFO +115 -0
  2. splunkctl-0.14.0/README.md +73 -0
  3. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/alerts.md +3 -1
  4. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/apps.md +3 -1
  5. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/audit.md +16 -14
  6. splunkctl-0.14.0/docs/guides/auth.md +63 -0
  7. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/conf.md +7 -5
  8. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/configure.md +42 -12
  9. splunkctl-0.14.0/docs/guides/dashboards.md +108 -0
  10. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/datamodels.md +28 -26
  11. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/doctor.md +5 -8
  12. splunkctl-0.14.0/docs/guides/es-detections.md +98 -0
  13. splunkctl-0.14.0/docs/guides/es.md +101 -0
  14. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/exit-codes.md +3 -0
  15. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/hec.md +3 -1
  16. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/indexes.md +3 -1
  17. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/inputs.md +3 -1
  18. splunkctl-0.14.0/docs/guides/install.md +108 -0
  19. splunkctl-0.14.0/docs/guides/keycloak-lab.md +75 -0
  20. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/knowledge.md +12 -10
  21. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/kvstore.md +19 -17
  22. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/lookups.md +3 -1
  23. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/mcp.md +12 -10
  24. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/parsers.md +3 -1
  25. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/rules.md +7 -5
  26. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/search.md +6 -2
  27. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/server.md +4 -2
  28. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-actions.md +5 -3
  29. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-admin.md +3 -1
  30. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-approvals.md +3 -1
  31. splunkctl-0.14.0/docs/guides/soar-apps.md +76 -0
  32. splunkctl-0.14.0/docs/guides/soar-assets.md +104 -0
  33. splunkctl-0.14.0/docs/guides/soar-automation.md +8 -0
  34. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-cases.md +4 -2
  35. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-functions.md +3 -1
  36. splunkctl-0.14.0/docs/guides/soar-incidents.md +186 -0
  37. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-indicators.md +5 -3
  38. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-ingest.md +15 -13
  39. splunkctl-0.14.0/docs/guides/soar-lists.md +135 -0
  40. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-playbooks.md +9 -7
  41. splunkctl-0.14.0/docs/guides/soar.md +128 -0
  42. splunkctl-0.14.0/docs/guides/splunk-cli.md +42 -0
  43. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/state.md +7 -5
  44. {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/users.md +3 -1
  45. {splunkctl-0.12.0 → splunkctl-0.14.0}/pyproject.toml +5 -1
  46. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/__init__.py +1 -1
  47. splunkctl-0.14.0/splunkctl/auth/__init__.py +1 -0
  48. splunkctl-0.14.0/splunkctl/auth/adapters.py +151 -0
  49. splunkctl-0.14.0/splunkctl/auth/broker.py +115 -0
  50. splunkctl-0.14.0/splunkctl/auth/detector.py +120 -0
  51. splunkctl-0.14.0/splunkctl/auth/session.py +204 -0
  52. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/client.py +66 -9
  53. splunkctl-0.14.0/splunkctl/commands/auth.py +198 -0
  54. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/commands_meta.py +21 -10
  55. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/config_cmd.py +122 -14
  56. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/docs_cmd.py +65 -15
  57. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/doctor.py +49 -1
  58. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/hec.py +1 -1
  59. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/search.py +7 -0
  60. splunkctl-0.14.0/splunkctl/commands/soar/_client.py +81 -0
  61. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/_ingest_helpers.py +3 -0
  62. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/artifacts.py +6 -2
  63. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/assets.py +21 -3
  64. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/functions.py +2 -1
  65. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/playbooks.py +2 -1
  66. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_soar_assets.py +10 -6
  67. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/config.py +70 -12
  68. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/errors.py +12 -0
  69. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/guard.py +2 -2
  70. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/main.py +31 -3
  71. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/dynamic_server.py +9 -1
  72. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/resources.py +2 -0
  73. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/runner.py +3 -1
  74. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/output.py +2 -1
  75. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/client.py +12 -1
  76. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/web.py +11 -0
  77. splunkctl-0.14.0/splunkctl/spl_safety.py +64 -0
  78. splunkctl-0.14.0/splunkctl.egg-info/PKG-INFO +115 -0
  79. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/SOURCES.txt +13 -0
  80. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/entry_points.txt +1 -0
  81. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/requires.txt +4 -1
  82. splunkctl-0.12.0/PKG-INFO +0 -270
  83. splunkctl-0.12.0/README.md +0 -230
  84. splunkctl-0.12.0/docs/guides/dashboards.md +0 -17
  85. splunkctl-0.12.0/docs/guides/es.md +0 -236
  86. splunkctl-0.12.0/docs/guides/install.md +0 -55
  87. splunkctl-0.12.0/docs/guides/soar-apps.md +0 -56
  88. splunkctl-0.12.0/docs/guides/soar-automation.md +0 -132
  89. splunkctl-0.12.0/docs/guides/soar-lists.md +0 -110
  90. splunkctl-0.12.0/docs/guides/soar.md +0 -440
  91. splunkctl-0.12.0/splunkctl/commands/soar/_client.py +0 -44
  92. splunkctl-0.12.0/splunkctl.egg-info/PKG-INFO +0 -270
  93. {splunkctl-0.12.0 → splunkctl-0.14.0}/LICENSE +0 -0
  94. {splunkctl-0.12.0 → splunkctl-0.14.0}/MANIFEST.in +0 -0
  95. {splunkctl-0.12.0 → splunkctl-0.14.0}/setup.cfg +0 -0
  96. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/__main__.py +0 -0
  97. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/__init__.py +0 -0
  98. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/alerts.py +0 -0
  99. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/apps.py +0 -0
  100. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/audit.py +0 -0
  101. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/audit_parse.py +0 -0
  102. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/common.py +0 -0
  103. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/conf.py +0 -0
  104. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/conf_ops.py +0 -0
  105. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/dashboards.py +0 -0
  106. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/datamodels.py +0 -0
  107. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/es.py +0 -0
  108. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/es_threat_intel.py +0 -0
  109. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/indexes.py +0 -0
  110. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/info.py +0 -0
  111. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/inputs.py +0 -0
  112. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/knowledge.py +0 -0
  113. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/kvstore.py +0 -0
  114. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/lookups.py +0 -0
  115. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/lookups_wiring.py +0 -0
  116. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/mcp_cmd.py +0 -0
  117. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/parsers.py +0 -0
  118. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/parsers_io.py +0 -0
  119. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/rules.py +0 -0
  120. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/rules_io.py +0 -0
  121. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/rules_schedule.py +0 -0
  122. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server.py +0 -0
  123. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_auth.py +0 -0
  124. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_deployment.py +0 -0
  125. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_tokens.py +0 -0
  126. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_topology.py +0 -0
  127. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_workloads.py +0 -0
  128. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/__init__.py +0 -0
  129. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/actions.py +0 -0
  130. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/admin.py +0 -0
  131. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/admin_roles_audit.py +0 -0
  132. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/admin_views.py +0 -0
  133. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/approvals.py +0 -0
  134. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/apps.py +0 -0
  135. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/cases.py +0 -0
  136. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/containers.py +0 -0
  137. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/containers_assign.py +0 -0
  138. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/containers_write.py +0 -0
  139. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/indicators.py +0 -0
  140. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/ingest.py +0 -0
  141. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/lists.py +0 -0
  142. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/notes.py +0 -0
  143. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/playbook_runs.py +0 -0
  144. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/playbooks_delete.py +0 -0
  145. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/search.py +0 -0
  146. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/system.py +0 -0
  147. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/vault.py +0 -0
  148. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/workbook_templates.py +0 -0
  149. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state.py +0 -0
  150. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io.py +0 -0
  151. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_blobs.py +0 -0
  152. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_confs.py +0 -0
  153. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_soar.py +0 -0
  154. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_types.py +0 -0
  155. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/users.py +0 -0
  156. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/__init__.py +0 -0
  157. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/output_cap.py +0 -0
  158. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/prompts.py +0 -0
  159. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/server.py +0 -0
  160. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/tools.py +0 -0
  161. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/transport.py +0 -0
  162. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/py.typed +0 -0
  163. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/__init__.py +0 -0
  164. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/cimcef.py +0 -0
  165. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/dependency_links.txt +0 -0
  166. {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/top_level.txt +0 -0
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.4
2
+ Name: splunkctl
3
+ Version: 0.14.0
4
+ Summary: Open-source MCP server and CLI for Splunk Enterprise SIEM and Splunk SOAR.
5
+ Author: dannyota
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/dannyota/splunkctl
8
+ Project-URL: Documentation, https://splunkctl.danny.vn
9
+ Project-URL: Repository, https://github.com/dannyota/splunkctl
10
+ Project-URL: Issues, https://github.com/dannyota/splunkctl/issues
11
+ Project-URL: Changelog, https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md
12
+ Keywords: splunk,mcp,model-context-protocol,siem,soar,security,cli,detection,spl
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Security
20
+ Classifier: Topic :: System :: Systems Administration
21
+ Requires-Python: >=3.13
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: splunk-sdk>=2.0
25
+ Requires-Dist: click>=8.2
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: tabulate>=0.9
28
+ Requires-Dist: requests>=2.32
29
+ Requires-Dist: defusedxml>=0.7
30
+ Requires-Dist: mcp<3,>=2.3
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=8.0; extra == "dev"
33
+ Requires-Dist: ruff>=0.6; extra == "dev"
34
+ Requires-Dist: mypy>=1.11; extra == "dev"
35
+ Requires-Dist: types-requests; extra == "dev"
36
+ Requires-Dist: types-PyYAML; extra == "dev"
37
+ Requires-Dist: types-tabulate; extra == "dev"
38
+ Requires-Dist: types-defusedxml; extra == "dev"
39
+ Provides-Extra: browser
40
+ Requires-Dist: playwright>=1.45; extra == "browser"
41
+ Dynamic: license-file
42
+
43
+ # splunkctl
44
+
45
+ <a href="https://splunkctl.danny.vn"><img src="https://raw.githubusercontent.com/dannyota/splunkctl/master/docs/assets/banner.svg" alt="splunkctl: CLI and MCP server for Splunk Enterprise, Enterprise Security, and SOAR" width="600"></a>
46
+
47
+ Operate Splunk Enterprise, Enterprise Security, and Splunk SOAR from a terminal, or give an AI agent the same commands through MCP.
48
+
49
+ Requires Python 3.13+ and credentials for your Splunk instance.
50
+
51
+ ## Quickstart
52
+
53
+ ```bash
54
+ python -m pip install splunkctl
55
+ splunkctl config init
56
+ splunkctl doctor
57
+ ```
58
+
59
+ [Documentation](https://splunkctl.danny.vn) · [Installation requirements](https://splunkctl.danny.vn/#/guides/install)
60
+
61
+ ## Tasks
62
+
63
+ - Investigate: run SPL, read fired alerts, and triage Enterprise Security notables. [Search](https://splunkctl.danny.vn/#/guides/search), [Triage notables](https://splunkctl.danny.vn/#/guides/es)
64
+ - Deploy detections: export saved searches to YAML, review the diff, and import them on another instance. [Manage detection rules](https://splunkctl.danny.vn/#/guides/rules)
65
+ - Respond with SOAR: work containers, artifacts, vault files, notes, and playbook runs. [Work SOAR incidents](https://splunkctl.danny.vn/#/guides/soar-incidents)
66
+ - Review configuration drift: pull live state, diff it against version control, and push approved changes with a change report. [Manage configuration as code](https://splunkctl.danny.vn/#/guides/state)
67
+
68
+ ## Safety
69
+
70
+ Every command that changes a remote Splunk or SOAR instance is guarded. Without `--yes` it prints a preview and exits without changing anything; some previews read the current state first to show a diff. The preview names the target host, and the active profile for Splunk Enterprise, so a change aimed at production is visible before it happens:
71
+
72
+ ```text
73
+ $ splunkctl --profile uat rules delete 'My Rule'
74
+ [DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
75
+ Pass --yes to apply.
76
+ ```
77
+
78
+ Add `--yes` to apply. `splunkctl state push --report FILE` writes a change report with the before and after state for each object, which you can attach to a change ticket.
79
+
80
+ Local configuration writes are not guarded: `splunkctl config init`, `splunkctl config use`, `splunkctl auth login`, and `splunkctl mcp install` write to your own machine immediately.
81
+
82
+ ## Agent access
83
+
84
+ The MCP server exposes the command tree to Claude Code, Claude Desktop, Cursor, or any other MCP client. Setup, transports, and the progressive tool-loading model are in the [MCP guide](https://splunkctl.danny.vn/#/guides/mcp).
85
+
86
+ ```bash
87
+ splunkctl mcp install # register the server in ./.mcp.json
88
+ splunkctl commands --json # machine-readable command tree
89
+ ```
90
+
91
+ Guarded tools keep the same contract as the CLI: a call previews until the agent passes `yes=true` explicitly.
92
+
93
+ ## Requirements and limitations
94
+
95
+ - Python 3.13 or newer.
96
+ - A Splunk account with REST API access on port 8089 (or your configured port). Each command needs the Splunk capability or SOAR permission its action requires; `splunkctl doctor` reports which checks pass for the active profile.
97
+ - Enterprise Security commands (`splunkctl es ...`) check for the `SplunkEnterpriseSecuritySuite` app and exit 1 with a `not_found` error when it is not installed.
98
+ - Dashboard, lookup file, and HEC token commands use entity classes from an optional SDK fork. Install it with:
99
+
100
+ ```bash
101
+ python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
102
+ ```
103
+
104
+ - Browser SAML login needs the `browser` extra: `python -m pip install 'splunkctl[browser]'`.
105
+
106
+ ## Project and support
107
+
108
+ splunkctl is an independent community project. It is not affiliated with or endorsed by Splunk Inc.
109
+
110
+ Splunk Inc. publishes an unrelated Go CLI with the same executable name, [`splunk/splunkctl`](https://github.com/splunk/splunkctl). This package also installs `splunkctl-py` and leaves a Splunk-format config file untouched, so both tools can be installed together; see [Relationship to Splunk's splunkctl](https://splunkctl.danny.vn/#/guides/splunk-cli).
111
+
112
+ - [Releases](https://github.com/dannyota/splunkctl/releases) and [changelog](https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md)
113
+ - [Issues](https://github.com/dannyota/splunkctl/issues) for bugs and feature requests; see [SECURITY.md](SECURITY.md) for vulnerabilities
114
+ - [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
115
+ - License: [Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
@@ -0,0 +1,73 @@
1
+ # splunkctl
2
+
3
+ <a href="https://splunkctl.danny.vn"><img src="https://raw.githubusercontent.com/dannyota/splunkctl/master/docs/assets/banner.svg" alt="splunkctl: CLI and MCP server for Splunk Enterprise, Enterprise Security, and SOAR" width="600"></a>
4
+
5
+ Operate Splunk Enterprise, Enterprise Security, and Splunk SOAR from a terminal, or give an AI agent the same commands through MCP.
6
+
7
+ Requires Python 3.13+ and credentials for your Splunk instance.
8
+
9
+ ## Quickstart
10
+
11
+ ```bash
12
+ python -m pip install splunkctl
13
+ splunkctl config init
14
+ splunkctl doctor
15
+ ```
16
+
17
+ [Documentation](https://splunkctl.danny.vn) · [Installation requirements](https://splunkctl.danny.vn/#/guides/install)
18
+
19
+ ## Tasks
20
+
21
+ - Investigate: run SPL, read fired alerts, and triage Enterprise Security notables. [Search](https://splunkctl.danny.vn/#/guides/search), [Triage notables](https://splunkctl.danny.vn/#/guides/es)
22
+ - Deploy detections: export saved searches to YAML, review the diff, and import them on another instance. [Manage detection rules](https://splunkctl.danny.vn/#/guides/rules)
23
+ - Respond with SOAR: work containers, artifacts, vault files, notes, and playbook runs. [Work SOAR incidents](https://splunkctl.danny.vn/#/guides/soar-incidents)
24
+ - Review configuration drift: pull live state, diff it against version control, and push approved changes with a change report. [Manage configuration as code](https://splunkctl.danny.vn/#/guides/state)
25
+
26
+ ## Safety
27
+
28
+ Every command that changes a remote Splunk or SOAR instance is guarded. Without `--yes` it prints a preview and exits without changing anything; some previews read the current state first to show a diff. The preview names the target host, and the active profile for Splunk Enterprise, so a change aimed at production is visible before it happens:
29
+
30
+ ```text
31
+ $ splunkctl --profile uat rules delete 'My Rule'
32
+ [DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
33
+ Pass --yes to apply.
34
+ ```
35
+
36
+ Add `--yes` to apply. `splunkctl state push --report FILE` writes a change report with the before and after state for each object, which you can attach to a change ticket.
37
+
38
+ Local configuration writes are not guarded: `splunkctl config init`, `splunkctl config use`, `splunkctl auth login`, and `splunkctl mcp install` write to your own machine immediately.
39
+
40
+ ## Agent access
41
+
42
+ The MCP server exposes the command tree to Claude Code, Claude Desktop, Cursor, or any other MCP client. Setup, transports, and the progressive tool-loading model are in the [MCP guide](https://splunkctl.danny.vn/#/guides/mcp).
43
+
44
+ ```bash
45
+ splunkctl mcp install # register the server in ./.mcp.json
46
+ splunkctl commands --json # machine-readable command tree
47
+ ```
48
+
49
+ Guarded tools keep the same contract as the CLI: a call previews until the agent passes `yes=true` explicitly.
50
+
51
+ ## Requirements and limitations
52
+
53
+ - Python 3.13 or newer.
54
+ - A Splunk account with REST API access on port 8089 (or your configured port). Each command needs the Splunk capability or SOAR permission its action requires; `splunkctl doctor` reports which checks pass for the active profile.
55
+ - Enterprise Security commands (`splunkctl es ...`) check for the `SplunkEnterpriseSecuritySuite` app and exit 1 with a `not_found` error when it is not installed.
56
+ - Dashboard, lookup file, and HEC token commands use entity classes from an optional SDK fork. Install it with:
57
+
58
+ ```bash
59
+ python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
60
+ ```
61
+
62
+ - Browser SAML login needs the `browser` extra: `python -m pip install 'splunkctl[browser]'`.
63
+
64
+ ## Project and support
65
+
66
+ splunkctl is an independent community project. It is not affiliated with or endorsed by Splunk Inc.
67
+
68
+ Splunk Inc. publishes an unrelated Go CLI with the same executable name, [`splunk/splunkctl`](https://github.com/splunk/splunkctl). This package also installs `splunkctl-py` and leaves a Splunk-format config file untouched, so both tools can be installed together; see [Relationship to Splunk's splunkctl](https://splunkctl.danny.vn/#/guides/splunk-cli).
69
+
70
+ - [Releases](https://github.com/dannyota/splunkctl/releases) and [changelog](https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md)
71
+ - [Issues](https://github.com/dannyota/splunkctl/issues) for bugs and feature requests; see [SECURITY.md](SECURITY.md) for vulnerabilities
72
+ - [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
73
+ - License: [Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
@@ -1,4 +1,6 @@
1
- # Alerts
1
+ <!-- summary: Review fired alerts, inspect alert actions, and manage alert suppression on a Splunk instance from the terminal. -->
2
+
3
+ # Review fired alerts
2
4
 
3
5
  Fired alerts are the SOC's incoming work queue. During an incident, you
4
6
  need to see what triggered, when, and at what severity. During planned
@@ -1,4 +1,6 @@
1
- # Apps
1
+ <!-- summary: Install, update, reload, and uninstall Splunk apps from local packages with a preview before every change. -->
2
+
3
+ # Manage apps
2
4
 
3
5
  Splunk's detection and enrichment capabilities live in apps --
4
6
  Technology Add-ons (TAs) for data normalization, security content packs
@@ -1,8 +1,10 @@
1
- # Change audit & RBAC attestation
1
+ <!-- summary: Produce change-audit and role-based access control attestation reports from Splunk for regulators and reviewers. -->
2
+
3
+ # Audit changes and attest RBAC
2
4
 
3
5
  Regulator-facing evidence for bank SOC operations: who changed what
4
6
  (`audit changes`) and who can do what (`audit rbac`). Both commands are
5
- **read-only** — no `guard`, no `--yes` needed.
7
+ **read-only**, no `guard`, no `--yes` needed.
6
8
 
7
9
  ## Why this matters
8
10
 
@@ -10,7 +12,7 @@ Banks carry regulator obligations for change-management evidence ("who
10
12
  changed this saved search / role / index, and when") and periodic access
11
13
  recertification ("who has which capabilities, and why"). Today an agent
12
14
  would have to hand-write `index=_audit` SPL and know that Splunk mixes
13
- **two incompatible event shapes** in that one index — this group
15
+ **two incompatible event shapes** in that one index, this group
14
16
  normalizes both into one schema and joins the RBAC graph so neither
15
17
  requires bespoke SPL per engagement.
16
18
 
@@ -37,11 +39,11 @@ sourcetypes and this command normalizes both:
37
39
 
38
40
  | Sourcetype | Shape | Mapping |
39
41
  |---|---|---|
40
- | `audittrail` (legacy) | `Audit:[timestamp=..., user=..., action=..., <tail>]` plain text | `user`/`action` parsed directly; `object` only when the line carries a literal `object="..."` marker (common on capability checks like `edit_user`/`edit_roles`); `object_type` is always empty — the legacy format has no per-action type field; `app` from `app="..."` or unquoted `app=...`, when present |
42
+ | `audittrail` (legacy) | `Audit:[timestamp=..., user=..., action=..., <tail>]` plain text | `user`/`action` parsed directly; `object` only when the line carries a literal `object="..."` marker (common on capability checks like `edit_user`/`edit_roles`); `object_type` is always empty, the legacy format has no per-action type field; `app` from `app="..."` or unquoted `app=...`, when present |
41
43
  | `audittrailv2` (structured) | one JSON object per line | `user` = `actor.name`; `action` = top-level `action`; `object` = `data.name`; `object_type` = `data.type`; `app` = `data.ownership.app` or `data.attributes.app` |
42
44
 
43
45
  `time` always comes from Splunk's own indexed `_time` (not a re-parse of
44
- either embedded timestamp format) — it's present on every event
46
+ either embedded timestamp format), it's present on every event
45
47
  regardless of shape and gives one consistent, sortable value.
46
48
 
47
49
  There is no literal `data.object`/`data.object_type` key on real
@@ -49,20 +51,20 @@ There is no literal `data.object`/`data.object_type` key on real
49
51
  equivalents and confirmed present for object/system-category events
50
52
  (config changes). Action/authn/check-category events (ad-hoc searches,
51
53
  logins, capability grants) carry `data.type` sometimes but rarely
52
- `data.name` — `object` stays empty for those, which is correct: they
54
+ `data.name`, `object` stays empty for those, which is correct: they
53
55
  aren't changes to a named object.
54
56
 
55
- An event matching neither shape is **never dropped** — it comes back as
57
+ An event matching neither shape is **never dropped**, it comes back as
56
58
  `action: "unparsed"` with the full raw line in `object`, so evidence
57
59
  stays complete even for audit-log formats this parser doesn't yet know.
58
60
 
59
61
  ## `audit changes`: SPL safety
60
62
 
61
- The dispatched search is always the constant `search index=_audit` —
63
+ The dispatched search is always the constant `search index=_audit`,
62
64
  nothing else, ever. `--since`/`--until` go through the oneshot job's
63
65
  `earliest_time`/`latest_time` kwargs (not string-composed), and
64
66
  `--user`/`--action`/`--object-type` filter the already-normalized rows
65
- **client-side**, after the fetch. No flag value — however adversarial —
67
+ **client-side**, after the fetch. No flag value, however adversarial,
66
68
  reaches the SPL string. Verified live with `--debug`:
67
69
 
68
70
  ```bash
@@ -72,7 +74,7 @@ POST .../search/v2/jobs/ (body: {'search': 'search index=_audit', ...})
72
74
  ```
73
75
 
74
76
  `--limit` (default 500) applies **after** filtering, not to the raw
75
- fetch — the raw fetch itself is unbounded (`count=0`) within the
77
+ fetch, the raw fetch itself is unbounded (`count=0`) within the
76
78
  `--since`/`--until` window, so a `--user`/`--action` filter never misses
77
79
  a match just because it fell outside an arbitrary raw-fetch cutoff.
78
80
  A very wide `--since` over a large `_audit` index may fetch all events in that range before limiting, which can be slow; narrow `--since` when possible.
@@ -83,7 +85,7 @@ A very wide `--since` over a large `_audit` index may fetch all events in that r
83
85
  One row per user by default: `user`, `email`, `roles` (direct roles,
84
86
  semicolon-joined), `capabilities`, `srch_indexes_allowed`. The last two
85
87
  are aggregated across the user's direct roles **and the full transitive
86
- closure of their imported roles** — deduplicated, sorted, and
88
+ closure of their imported roles**, deduplicated, sorted, and
87
89
  semicolon-joined. `--roles-only` flips to one row per role instead:
88
90
  `role`, `imported_roles` (direct only), `capabilities`,
89
91
  `srch_indexes_allowed` (both aggregated the same transitive way, rooted
@@ -91,14 +93,14 @@ at that role).
91
93
 
92
94
  Example: role `soc_analyst` imports `power`, which imports `user`. A
93
95
  `soc_analyst` user's effective `capabilities` is the union of all three
94
- roles' own capabilities — this is what a role with zero capabilities of
96
+ roles' own capabilities, this is what a role with zero capabilities of
95
97
  its own (e.g. Splunk's built-in `splunk-system-role`, which only imports
96
98
  `admin`) needs to show its real effective grant, not an empty cell.
97
99
 
98
100
  ## CSV round-trip safety
99
101
 
100
102
  Multi-value fields (`roles`, `capabilities`, `srch_indexes_allowed`,
101
- `imported_roles`) join with `;`, never `\n` — Splunk role/capability/index
103
+ `imported_roles`) join with `;`, never `\n`, Splunk role/capability/index
102
104
  names can't contain a semicolon, so this is a safe, lossless join that
103
105
  never produces an embedded newline inside a CSV cell. `--format csv`
104
106
  output round-trips cleanly through Python's `csv` module.
@@ -121,5 +123,5 @@ output round-trips cleanly through Python's `csv` module.
121
123
  (`svc.jobs.oneshot`); the event-shape parsers live in a sibling module,
122
124
  `splunkctl/commands/audit_parse.py`, kept separate from the click
123
125
  commands since they're pure functions with their own fixture-driven test
124
- suite. `rbac` is SDK reads only (`svc.roles`, `svc.users`) — no oneshot
126
+ suite. `rbac` is SDK reads only (`svc.roles`, `svc.users`), no oneshot
125
127
  search involved.
@@ -0,0 +1,63 @@
1
+ <!-- summary: Complete Splunk and SOAR SAML single sign-on, including a second factor, in a browser and reuse the session from every splunkctl command. -->
2
+
3
+ # Log in through browser SAML
4
+
5
+ splunkctl can complete Splunk SAML single sign-on (including a second factor)
6
+ in a headed Chromium window and then reuse the resulting product session until
7
+ it expires. The browser handles the identity provider; splunkctl never reads or
8
+ stores TOTP secrets or codes.
9
+
10
+ ## How it works
11
+
12
+ 1. `splunkctl config init --web-url https://splunk.example.com` probes the public login route. When it sees a
13
+ redirect to an external identity provider, it records `auth_mode: browser`
14
+ and stores the product `web_url`.
15
+ 2. `splunkctl auth login --target <siem|soar>` opens Chromium at the product
16
+ login route. You complete the IdP prompts, including any TOTP code.
17
+ 3. splunkctl extracts only the product session (Splunk `splunkd_<port>` cookie,
18
+ or SOAR `sessionid` + `csrftoken`) and proves it against the product API.
19
+ 4. Normal commands reuse the cached session whenever the active profile selects
20
+ browser mode. A missing or expired session never opens a browser; the command
21
+ prints the exact login instruction instead.
22
+
23
+ ## Commands
24
+
25
+ ```text
26
+ splunkctl auth login --target siem
27
+ splunkctl auth login --target soar
28
+ splunkctl auth status [--target siem|soar|both]
29
+ splunkctl auth logout [--target siem|soar|both]
30
+ ```
31
+
32
+ `login` requires exactly one target; two back-to-back browser flows are easy to
33
+ confuse. `status` reports `missing`, `valid`, `expired`, or `unreachable`.
34
+ `logout` always removes the local session, even if the remote endpoint refuses.
35
+
36
+ ## Optional dependency
37
+
38
+ Browser login needs Playwright and Chromium:
39
+
40
+ ```bash
41
+ pip install 'splunkctl[browser]'
42
+ python -m playwright install chromium
43
+ ```
44
+
45
+ Configuration still succeeds without them. `splunkctl auth login` prints the
46
+ exact commands when they are missing.
47
+
48
+ ## Session storage and security
49
+
50
+ Sessions are stored under `~/.splunkctl/sessions/<profile>/<target>.json` with
51
+ directory mode `0700` and file mode `0600`. A record holds only the target,
52
+ profile, product origin, product session values, and validation timestamps. It
53
+ never stores passwords, Playwright storage state, identity-provider cookies, or
54
+ TOTP secrets. Session values are redacted from all output.
55
+
56
+ ## What is and is not supported
57
+
58
+ Supported: SAML browser login for SIEM and SOAR, one target per login, session
59
+ status and logout, automatic SAML detection, and a reusable Keycloak lab.
60
+
61
+ Not supported in this release: reading or storing TOTP secrets, native Splunk
62
+ Duo or RSA flows, OpenID Connect or OAuth, logging in to both products in one
63
+ command, and a local splunkctl callback redirect.
@@ -1,6 +1,8 @@
1
- # Conf
1
+ <!-- summary: Read and edit any Splunk configuration file and stanza over the REST confs API when no dedicated command group covers it. -->
2
2
 
3
- Generic conf file/stanza editor over the REST `confs` API — the escape
3
+ # Edit any conf file
4
+
5
+ Generic conf file/stanza editor over the REST `confs` API, the escape
4
6
  hatch for any Splunk conf file that doesn't have a dedicated command
5
7
  group yet: `macros`, `eventtypes`, `tags`, `limits`, `authorize`,
6
8
  `server`, `web`, and everything else under `$SPLUNK_HOME/etc/*/local`.
@@ -14,7 +16,7 @@ and calculated fields live in `props.conf` alongside sourcetypes.
14
16
  every other conf file the same way, so nothing detection-relevant is
15
17
  locked out of code review or CI.
16
18
 
17
- There is **no blocklist** — `conf` can edit `authorize.conf`,
19
+ There is **no blocklist**, `conf` can edit `authorize.conf`,
18
20
  `server.conf`, and `web.conf` just as readily as `macros.conf`. The
19
21
  dry-run guard and `--yes` are the only safety net: every `set`/`unset`/
20
22
  `reload` preview names the exact file and stanza before it touches
@@ -54,7 +56,7 @@ splunkctl conf get eventtypes authentication --json | jq .
54
56
 
55
57
  ### Review a stanza change before applying
56
58
 
57
- `conf set` always previews a field-level diff — old value on the left,
59
+ `conf set` always previews a field-level diff, old value on the left,
58
60
  new value on the right, `add` for a brand-new key:
59
61
 
60
62
  ```bash
@@ -71,7 +73,7 @@ splunkctl conf files --filter tag
71
73
 
72
74
  ## Tips
73
75
 
74
- - `conf set` creates the stanza if it doesn't exist yet — there's no
76
+ - `conf set` creates the stanza if it doesn't exist yet, there's no
75
77
  separate create step.
76
78
  - The REST API has no true per-key delete; `conf unset` sets keys to
77
79
  the empty string (same mechanism `parsers unset` uses). To fully
@@ -1,3 +1,5 @@
1
+ <!-- summary: Set up splunkctl profiles for development, UAT, and production, and override them with environment variables or flags. -->
2
+
1
3
  # Configure
2
4
 
3
5
  ## Interactive setup
@@ -6,8 +8,10 @@
6
8
  splunkctl config init
7
9
  ```
8
10
 
9
- Prompts for host, port, auth method (token or username/password), tests the
10
- connection, and writes `~/.splunkctl/config.yaml` with `0600` permissions.
11
+ Prompts for host, port, username, password, and TLS verification, then writes
12
+ `~/.splunkctl/config.yaml` with `0600` permissions. SAML detection runs only
13
+ when `--web-url URL` is supplied. Run `splunkctl config test` to check
14
+ connectivity and authentication after setup.
11
15
 
12
16
  ## Config file
13
17
 
@@ -27,7 +31,7 @@ owner: "nobody" # default owner context
27
31
 
28
32
  **TLS verification is on by default.** Production instances with valid
29
33
  certificates work out of the box. For lab/dev instances with self-signed
30
- certs, set `verify: false` explicitly in the profile — `config init` asks
34
+ certs, set `verify: false` explicitly in the profile, `config init` asks
31
35
  during setup (default: yes).
32
36
 
33
37
  ## Profiles (dev/UAT/prod)
@@ -62,8 +66,8 @@ splunkctl --profile prod rules list # override for a single invocation
62
66
  pointer > `default`.
63
67
 
64
68
  **Legacy files keep working.** A plain flat file (no `profiles:` key) is
65
- treated as an implicit profile named `default` — nothing to migrate. Bare
66
- `config init` writes that flat shape — unless the destination file already
69
+ treated as an implicit profile named `default`, nothing to migrate. Bare
70
+ `config init` writes that flat shape, unless the destination file already
67
71
  has a `profiles:` key, in which case it folds the new values into
68
72
  `profiles.default` instead, leaving sibling profiles and `current`
69
73
  untouched (bare `config init` never clobbers an existing multi-profile
@@ -73,8 +77,8 @@ keys move under `profiles.default`, the new named profile is added
73
77
  alongside it, and file permissions stay `0600`.
74
78
 
75
79
  **Guard banner.** Every dry-run preview and `--yes` confirmation prints
76
- which instance is about to be mutated —
77
- `[DRY RUN] ... (profile: uat @ uat.splunk.internal:8089)` — so switching
80
+ which instance is about to be mutated,
81
+ `[DRY RUN] ... (profile: uat @ uat.splunk.internal:8089)`, so switching
78
82
  between dev/UAT/prod never happens silently. The banner is built from local
79
83
  config only; it never opens a connection.
80
84
 
@@ -88,14 +92,40 @@ config only; it never opens a connection.
88
92
  | `SPLUNK_USER` | `username` |
89
93
  | `SPLUNK_PASS` | `password` |
90
94
 
91
- Env vars override fields of whichever profile is selected — same as they
92
- override the flat config today.
95
+ Environment variables override fields in the selected profile.
93
96
 
94
97
  ## Resolution priority
95
98
 
96
- 1. CLI flags (`--host`, `--port`, `--token`)
97
- 2. Environment variables
98
- 3. Profile (config file)
99
+ 1. Environment variables
100
+ 2. Selected profile
101
+ 3. Built-in defaults
102
+
103
+ `--profile` and `--config` are the only root options that select configuration.
104
+
105
+ ## Coexistence with Splunk's splunkctl
106
+
107
+ Splunk's own Go CLI, [`splunk/splunkctl`](https://github.com/splunk/splunkctl),
108
+ also writes `~/.splunkctl/config.yaml`, as a flat file with `host` (a full
109
+ URL) and `token`. This tool never rewrites that file.
110
+
111
+ - When `~/.splunkctl/config.yaml` is in Splunk's format and no `--config`
112
+ is given, this tool reads and writes `~/.splunkctl/profiles.yaml`
113
+ instead and prints one notice on standard error:
114
+ `Splunk-format config at ~/.splunkctl/config.yaml; using ~/.splunkctl/profiles.yaml`.
115
+ - `splunkctl config init` writes to the same fallback file, so a single
116
+ `config init` is enough on a host that already has Splunk's tool.
117
+ - An explicit `--config FILE` is never redirected. If that file is in
118
+ Splunk's format, the command fails with
119
+ `Splunk-format config at FILE: this is a flat host/token file written by Splunk's splunkctl. Pass a profiles file with --config, or create one with: splunkctl config init --path FILE`
120
+ - `splunkctl doctor` reports the config file in use as its first check.
121
+ - A hand-written file of this tool's own legacy flat format that contains
122
+ only `host` and `token` is indistinguishable from Splunk's format and is
123
+ treated the same way. Add `port` or `scheme`, or run `config init`, to
124
+ keep using it.
125
+
126
+ Both tools install an executable named `splunkctl`. This package also
127
+ installs `splunkctl-py`, which runs the same CLI, for hosts where Splunk's
128
+ binary comes first on `PATH`.
99
129
 
100
130
  ## Watch mode
101
131
 
@@ -0,0 +1,108 @@
1
+ <!-- summary: Export Splunk dashboards to files, keep them in version control, and create, update, share, or delete them with a preview before every change. -->
2
+
3
+ # Manage dashboards
4
+
5
+ When to use: you want dashboard XML or Studio JSON in version control, need to copy a dashboard between instances, or must change who can see one.
6
+
7
+ ## Prerequisites
8
+
9
+ - The optional SDK fork, because dashboard commands use its `Dashboard` entity classes:
10
+
11
+ ```bash
12
+ python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
13
+ ```
14
+
15
+ - A Splunk account with write access to the target app (for example the `admin` or `power` role in `search`).
16
+
17
+ ## Synopsis
18
+
19
+ ```text
20
+ splunkctl dashboards list [--app APP] [--all] [--filter SUBSTRING] [--limit N] [--offset N]
21
+ splunkctl dashboards get <NAME> [--app APP] [--definition]
22
+ splunkctl dashboards export [NAME] [--app APP] [--out FILE] [--definition] [--all --dir DIR]
23
+ splunkctl dashboards create --name <NAME> --file <FILE> [--app APP] [--type classic|studio|auto] [--sharing user|app|global] [--yes]
24
+ splunkctl dashboards update <NAME> --file <FILE> [--app APP] [--type classic|studio|auto] [--yes]
25
+ splunkctl dashboards share <NAME> --sharing <user|app|global> [--owner USER] [--app APP] [--yes]
26
+ splunkctl dashboards delete <NAME> [--app APP] [--yes]
27
+ ```
28
+
29
+ `--app` defaults to `search` for the mutation commands.
30
+
31
+ ## Workflow
32
+
33
+ ### List and inspect
34
+
35
+ ```bash
36
+ splunkctl dashboards list
37
+ splunkctl dashboards list --app search --filter soc
38
+ splunkctl dashboards get soc_overview --app search
39
+ splunkctl dashboards get soc_studio --definition
40
+ ```
41
+
42
+ `list` shows dashboards only; add `--all` to include other views. `--filter`, `--limit`, and `--offset` apply client side after the app and type filters. `get` prints the XML source; `--definition` extracts the Studio JSON and errors on a Classic dashboard.
43
+
44
+ ### Export to files
45
+
46
+ ```bash
47
+ splunkctl dashboards export soc_overview --out dashboards/soc_overview.xml
48
+ splunkctl dashboards export soc_studio --definition --out dashboards/soc_studio.json
49
+ splunkctl dashboards export --all --dir dashboards/
50
+ ```
51
+
52
+ Expected result: one file per dashboard, ready to commit. `--out` overwrites without prompting.
53
+
54
+ ### Create a dashboard from a file
55
+
56
+ > **Safety:** Target is the Splunk host and app in the active profile (`--app`, default `search`). Impact: a new dashboard appears in that app. Preview with `splunkctl dashboards create --name new_dash --file dash.xml --app search`, apply by adding `--yes`, and verify with `splunkctl dashboards get new_dash --app search`.
57
+
58
+ ```bash
59
+ splunkctl dashboards create --name new_dash --file dash.xml --app search
60
+ splunkctl dashboards create --name new_dash --file dash.xml --app search --yes
61
+ splunkctl dashboards create --name new_dash --file dash.json --type studio --sharing app --yes
62
+ ```
63
+
64
+ `--type auto` (the default) detects Classic XML or Studio JSON from the file.
65
+
66
+ ### Update a dashboard
67
+
68
+ > **Safety:** Target is the Splunk host and app in the active profile. Impact: the dashboard source is replaced with the file's content. Preview with `splunkctl dashboards update soc_overview --file updated.xml`, apply by adding `--yes`, and verify with `splunkctl dashboards get soc_overview`.
69
+
70
+ ```bash
71
+ splunkctl dashboards update soc_overview --file updated.xml --app search
72
+ splunkctl dashboards update soc_overview --file updated.xml --app search --yes
73
+ ```
74
+
75
+ Export first so you can restore the previous version if needed.
76
+
77
+ ### Change sharing
78
+
79
+ > **Safety:** Target is the Splunk host and app in the active profile. Impact: who can see the dashboard changes; `global` makes it visible from every app. Preview with `splunkctl dashboards share soc_overview --sharing app`, apply by adding `--yes`, and verify with `splunkctl dashboards list --filter soc_overview --json` (check `sharing`).
80
+
81
+ ```bash
82
+ splunkctl dashboards share soc_overview --sharing app --yes
83
+ splunkctl dashboards share soc_overview --sharing global --owner admin --yes
84
+ ```
85
+
86
+ ### Delete a dashboard
87
+
88
+ > **Safety:** Target is the Splunk host and app in the active profile. Impact: the dashboard is removed and cannot be recovered except from an export. Preview with `splunkctl dashboards delete old_dash --app search`, apply by adding `--yes`, and verify with `splunkctl dashboards list --app search --filter old_dash`.
89
+
90
+ ```bash
91
+ splunkctl dashboards export old_dash --out backup/old_dash.xml
92
+ splunkctl dashboards delete old_dash --app search
93
+ splunkctl dashboards delete old_dash --app search --yes
94
+ ```
95
+
96
+ ## Troubleshooting
97
+
98
+ - `ImportError` or a message about missing `Dashboard` classes: install the SDK fork listed under Prerequisites.
99
+ - `not_found` on `get` or `update`: pass `--app`; the dashboard may live outside `search`.
100
+ - `--definition` errors: the dashboard is Classic XML, not Studio.
101
+ - `permission` on create or share: the account lacks write access to the app, or `global` sharing needs the `admin_all_objects` capability.
102
+
103
+ ## See also
104
+
105
+ - [Manage configuration as code](state.md), which pulls and diffs dashboards
106
+ - [Run searches](search.md)
107
+ - [Install](install.md)
108
+ - [Command reference: dashboards](../commands/dashboards.md)