A Git-inspired CLI tool for managing Kibana saved objects in version control. Built with Rust for reliability, speed, and modern DevOps workflows.
kibob (Kibana Object Manager) helps you manage Kibana dashboards, visualizations, workflows, agents, tools, spaces, and other Kibana assets using a familiar Git-like workflow. Version control your Kibana artifacts alongside your application code, deploy them across environments, and collaborate with your team using standard Git practices.
- Git-like workflow -
pull,push, and version control your Kibana assets - Spaces management - Version control and deploy Kibana spaces alongside assets
- Workflows, agents, tools, and skills - Manage newer Kibana APIs alongside saved objects
- Environment management - Easy deployment across dev, staging, and production
- Manifest-based tracking - Explicitly define which objects, spaces, workflows, agents, tools, and skills to manage
- Managed vs. unmanaged - Control whether saved objects can be edited in the Kibana UI
- Flexible filtering - Target specific spaces and APIs with
--spaceand--api - Modern architecture - Built with Rust and a composable ETL pipeline
- Fast and reliable - Concurrent requests, proper error handling, and deterministic file layouts
Published on:
- Homebrew tap: https://github.com/VimCommando/homebrew-tools
- crates.io: https://crates.io/crates/kibana-object-manager
brew tap VimCommando/tools && brew install kibobcargo install kibana-object-managergit clone https://github.com/VimCommando/kibana-object-manager.git
cd kibana-object-manager
cargo build --release
# Binary will be at target/release/kibobThis repository also publishes kibana-sync as a standalone library for Rust
applications that need Kibana API behavior without the kibob project layout or
CLI policy.
[dependencies]
kibana-sync = "0.4"use kibana_sync::{Auth, KibanaClient};
use url::Url;
# async fn run() -> kibana_sync::Result<()> {
let client = KibanaClient::builder(Url::parse("http://localhost:5601")?)
.auth(Auth::basic("elastic", "changeme"))
.max_concurrency(8)
.spaces([
("default".to_string(), "Default".to_string()),
("esdiag".to_string(), "ESDiag".to_string()),
])
.build()?;
let esdiag = client.space("esdiag")?;
let version = esdiag.server_version().await?;
# Ok(())
# }kibana-sync exposes saved objects, spaces, agents, tools, skills, workflows,
capability gates, dependency discovery, tracing instrumentation, and
storage-neutral sync models. It does not read spaces.yml; kibob reads that
file in the CLI crate and passes the resulting registry into the library.
You can either export variables in your shell or store them in a dotenv file and use --env.
export KIBANA_URL=http://localhost:5601
export KIBANA_USERNAME=elastic
export KIBANA_PASSWORD=changeme
# OR use API key authentication:
# export KIBANA_APIKEY=your_api_key_hereExample .env file:
KIBANA_URL=http://localhost:5601
KIBANA_USERNAME=elastic
KIBANA_PASSWORD=changeme
KIBANA_MAX_REQUESTS=8kibob auth
kibob --env local authFirst, export your dashboards from Kibana UI (Stack Management → Saved Objects → Export).
kibob init export.ndjson ./my-dashboards
cd my-dashboardsThis creates:
manifest/saved_objects.json- tracks which saved objects to manageobjects/- directory with your exported objects organized by type
Optional: Add spaces management
Create a top-level spaces.yml to manage Kibana spaces:
spaces:
- id: default
name: Default
- id: marketing
name: Marketing
- id: engineering
name: EngineeringNow pull, push, and togo can also manage spaces. Each space definition is stored at {space_id}/space.json.
Optional: Add workflows, agents, tools, and skills
Create per-space manifests like these:
workflows:
- id: workflow-123
name: my-workflow
- id: workflow-456
name: alert-workflow
- id: workflow-789
name: data-pipelineagents:
- id: agent-123
name: support-agenttools:
- id: search-tool
name: search-toolskills:
- id: threat-hunting-copy
name: threat-hunting-copyNow pull, push, and togo will also manage those APIs for each configured space.
Skills are stored as directories instead of JSON files:
default/
manifest/
skills.yml
skills/
my-skill/
SKILL.md
examples/
query.md
manifest/skills.yml lists the tracked Skills for the space by id and name. Skill directory names use the Kibana Skill id directly; Kibana requires IDs to start and end with a lowercase letter or number and contain only lowercase letters, numbers, hyphens, and underscores. The frontmatter id remains authoritative. When the manifest exists, push and togo include only the listed Skills in manifest order; when it is absent, all skills/*/SKILL.md directories are discovered.
SKILL.md contains YAML frontmatter with id, name, description, tool_ids, and experimental; the markdown body is the API content field. Every other file under the skill directory becomes a referenced_content entry when bundling or pushing: its filename without the extension becomes name, its parent directory becomes relativePath (examples/query.json is projected as ./examples), and its contents become content. The experimental field is preserved locally but omitted from create/update API requests because Kibana 9.4 rejects it in request bodies.
git init
git add .
git commit -m "Initial dashboard import"kibob pull
kibob pull --space default,marketing --api saved_objects,workflows,agents,tools,skills
git diff
git add . && git commit -m "Update from Kibana"export KIBANA_URL=https://prod-kibana.example.com
export KIBANA_APIKEY=prod_api_key
# Deploy as managed objects (read-only in Kibana UI)
kibob push --managed trueOr with dotenv files:
kibob --env stage push --managed false
kibob --env prod push --managed trueThese options work with every command:
--env <FILE>- load environment variables from a dotenv file. Default:.env. Shorthand values likedev,stage, orprodresolve to.env.dev,.env.stage, and.env.prod--debug- enable debug-level logging
Test connection and authentication to Kibana with the current credentials.
Examples:
kibob auth
kibob --env prod authInitialize a new project from a Kibana NDJSON export file.
Defaults:
exportdefaults toexport.ndjsonoutput_dirdefaults tomanifest.jsonin the current CLI definition
Examples:
kibob init export.ndjson ./my-dashboards
kibob init ./exports ./my-dashboards
kibob initNotes:
- If the first argument is a directory,
kiboblooks forexport.ndjsoninside it. initwrites:manifest/saved_objects.jsonobjects/...
Fetch managed content from Kibana into local files.
Defaults:
dirdefaults to.- if
--spaceis omitted,pulloperates on all managed spaces known to the client - if
--apiis omitted,pullprocesses all supported APIs
Supported API filters:
saved_objectsobjectsworkflowsagentstoolsskillsspaces
Examples:
kibob pull
kibob pull --space default,marketing
kibob pull --api saved_objects,workflows,agents,tools,skills
kibob --env dev pull --space default --api spacesNotes:
--spaceaccepts a comma-separated list.spacesare pulled from top-levelspaces.ymlif it exists.- Per-space workflows, agents, and tools are pulled when their manifests exist:
{space_id}/manifest/workflows.yml{space_id}/manifest/agents.yml{space_id}/manifest/tools.yml
- Per-space skills are pulled from the Skills API and written under
{space_id}/skills/. - Skills require Kibana 9.4.0 or newer and are experimental as of Kibana 9.4.
Upload local content to Kibana.
Defaults:
dirdefaults to.--managed true- if
--spaceis omitted,pushoperates on all managed spaces known to the client - if
--apiis omitted,pushprocesses all supported APIs
Supported API filters:
saved_objectsobjectsworkflowsagentstoolsskillsspaces
Examples:
kibob push --managed true
kibob push --managed false --space default,marketing
kibob push --api tools,agents,skills
kibob --env prod push --space production --api saved_objects,workflows --managed trueOptions:
--managed true- saved objects are marked managed/read-only in Kibana UI--managed false- saved objects remain editable in Kibana UI--space <...>- comma-separated list of target space IDs--api <...>- comma-separated list of APIs to push- Skills are tracked in
{space_id}/manifest/skills.ymland projected from{space_id}/skills/*/SKILL.mddirectories to Kibana JSON only when pushing.
Move one file-backed API family without creating or consulting a kibob project:
kibob import <skills|tools|agents|workflows> <source> [--space <id>] [--force]
kibob export <skills|tools|agents|workflows> <destination> \
(--id <resource-id>... | --all) [--space <id>] [--overwrite] [--force]Standalone import accepts these existing project artifact layouts:
skills: one directory containingSKILL.md, or a collection root whose immediate child directories containSKILL.md.tools,agents, andworkflows: one.jsonfile, or a directory of immediate.jsonfiles. Files use the existing JSON5 parser, including comments, trailing commas, and triple-quoted multiline strings.
Export always treats the destination as a collection root. Skills are written to
<destination>/<skill-id>/SKILL.md with referenced content. Tools, Agents, and
Workflows are written as immediate .json files using their existing project
filenames and multiline formatting.
Examples:
kibob import skills ./skills/threat-hunting --space security
kibob import tools ./tools
kibob export agents ./agent-backup --id triage-agent --id response-agent
kibob export workflows ./workflows --all --overwriteImports use create-or-update semantics and validate the complete local batch
before connecting to Kibana. Exports require an explicit --id or --all;
readonly resources are not exported because they cannot be re-imported under
the same ID. These commands never read or write skills.yml, tools.yml,
agents.yml, workflows.yml, or spaces.yml, and they do not expand
dependencies, prune remote resources, or change project-oriented push and
pull.
Add items to an existing manifest.
Supported APIs:
objectsworkflowsspacesagentstoolsskills
Common options:
--query <TEXT>- search query for API-backed discovery--include <REGEX>- include items whose name matches the regex--exclude <REGEX>- exclude items whose name matches the regex after include filtering--file <FILE>- load items from.jsonor.ndjson--space <space1,space2,...>- space selection/filtering--exclude-dependencies- do not automatically add discovered dependencies for workflows, agents, tools, or skills
Regex notes:
--includeand--excludeuse Rust regex syntax- include is applied first, then exclude
- use
(?i)for case-insensitive matching
kibob add workflows
kibob add workflows --space marketing
kibob add workflows --query "alert"
kibob add workflows --include "^prod"
kibob add workflows --exclude "test"
kibob add workflows --file export.json
kibob add workflows --exclude-dependencieskibob add agents
kibob add agents --space default
kibob add agents --include "^support"
kibob add agents --file agents.ndjson
kibob add agents --exclude-dependencieskibob add tools
kibob add tools --space default
kibob add tools --include "^search"
kibob add tools --file tools.ndjson
kibob add tools --exclude-dependencieskibob add skill threat-hunting
kibob add skills --space default
kibob add skills --query my-skill-id
kibob add skills --include "^triage"
kibob add skills --file skills.ndjson
kibob add skills --exclude-dependenciesThe singular shortcut kibob add skill <skill-id> fetches that exact Skill ID, tracks it in {space_id}/manifest/skills.yml, and writes it as {space_id}/skills/{skill-directory}/SKILL.md with referenced markdown files. Skills referenced by agents are written as skill directories, and a skill's tool_ids are added as tool dependencies unless --exclude-dependencies is used.
kibob add spaces
kibob add spaces --include "prod|staging"
kibob add spaces --exclude "(?i)test"
kibob add spaces --space default,marketing
kibob add spaces --file spaces.jsonkibob add objects --objects "dashboard=abc123,visualization=xyz789"
kibob add objects --file export.ndjsonImportant notes:
- For
objects,--objectsis required unless you use--file. - For
spaces,--queryis accepted by the CLI, but space discovery currently fetches all spaces and applies filtering afterward. - For non-
spacesAPIs, the CLI currently uses the first value from--spaceif multiple are supplied.
Bundle local content into distributable NDJSON files under bundle/.
Defaults:
dirdefaults to.--managed true
Supported API filters:
saved_objectsobjectsworkflowsagentstoolsskillsspaces
Generated outputs can include:
bundle/{space_id}/saved_objects.ndjsonbundle/{space_id}/workflows.ndjsonbundle/{space_id}/agents.ndjsonbundle/{space_id}/tools.ndjsonbundle/{space_id}/skills.ndjsonbundle/spaces.ndjson
Examples:
kibob togo
kibob togo --space default,marketing
kibob togo --api saved_objects,workflows,agents,tools,skills
zip -r dashboards.zip bundle/Notes:
bundle/spaces.ndjsonis generated when top-levelspaces.ymlexists.--apilets you create partial bundles for specific APIs only.skills.ndjsonis generated from skill directories; JSON is not the at-rest representation.
Migrate legacy project structure into the multi-space layout.
Defaults:
dirdefaults to.--backup true
Examples:
kibob migrate ./old-project
kibob migrate ./old-project --backup false
kibob --env local migrateMigration notes:
- Legacy content is moved into the target space layout:
{space_id}/manifest/saved_objects.json
- At runtime the target space is resolved from
KIBANA_SPACE, falling back todefault.
Back up and version control your dashboards. Easily restore or roll back changes.
Store dashboards and related Kibana assets in your application's Git repository. Deploy observability alongside code.
Automate dashboard and asset deployments in CI/CD pipelines. Keep environments consistent from dev to production.
- User Guide - Comprehensive command reference and workflows
- Architecture - Technical deep-dive for contributors
- Examples - Real-world usage scenarios
- Migration Guide - Migrating from legacy format
- Quick Reference - Command cheat sheet
- Contributing - Development guidelines
This repository includes a Codex skill for kibob workflows:
skills/kibob/SKILL.mdskills/kibob/references/kibob-commands.md
The skill is designed to help with:
- Selecting the right
kibobcommand and flags - Environment promotion workflows (
pull->git commit->push) - Managed mode policy by environment:
- Production:
--managed true - Dev/test:
--managed false
- Production:
Example promotion flow:
# Pull from dev
kibob --env dev pull --space dev --api saved_objects,workflows,agents,tools
git add .
git commit -m "Sync from dev"
# Push to stage (dev/test posture)
kibob --env stage push --space stage --api saved_objects,workflows,agents,tools --managed false
# Promote to production (production posture)
kibob --env prod push --space prod --api saved_objects,workflows,agents,tools --managed truekibob supports multiple authentication methods.
export KIBANA_USERNAME=elastic
export KIBANA_PASSWORD=changemeexport KIBANA_APIKEY=your_base64_encoded_keykibob uses a modern ETL (Extract-Transform-Load) pipeline architecture:
Pull: Kibana → Extract → Transform → Store Files
Push: Read Files → Transform → Load → Kibana
Built with:
- Rust - memory-safe, fast, reliable
- Tokio - async runtime for efficient I/O
- reqwest - HTTP client with connection pooling
- Clap - CLI framework
- serde - JSON serialization
- dotenvy - dotenv loading
- env_logger - CLI logging
- owo-colors - readable terminal output
A multi-space project typically looks like this:
my-dashboards/
├── spaces.yml
├── default/
│ ├── space.json
│ ├── manifest/
│ │ ├── saved_objects.json
│ │ ├── workflows.yml
│ │ ├── agents.yml
│ │ └── tools.yml
│ ├── objects/
│ │ ├── dashboard/
│ │ │ ├── abc-123.json
│ │ │ └── xyz-789.json
│ │ ├── visualization/
│ │ │ └── def-456.json
│ │ └── index-pattern/
│ │ └── logs-*.json
│ ├── workflows/
│ │ ├── my-workflow.json
│ │ └── alert-workflow.json
│ ├── agents/
│ │ └── my-agent.json
│ └── tools/
│ └── search-tool.json
├── marketing/
│ ├── space.json
│ ├── manifest/
│ │ ├── workflows.yml
│ │ └── tools.yml
│ ├── workflows/
│ │ └── campaign-workflow.json
│ └── tools/
│ └── campaign-tool.json
└── bundle/
├── default/
│ ├── saved_objects.ndjson
│ ├── workflows.ndjson
│ ├── agents.ndjson
│ └── tools.ndjson
├── marketing/
│ ├── workflows.ndjson
│ └── tools.ndjson
└── spaces.ndjson
A freshly initialized single-space project from kibob init starts simpler:
my-dashboards/
├── manifest/
│ └── saved_objects.json
└── objects/
kibob can manage Kibana Spaces alongside saved objects. Create a top-level spaces.yml:
spaces:
- id: default
name: Default
- id: marketing
name: Marketing
- id: engineering
name: EngineeringThen use the same workflow:
kibob pull # Pulls space definitions to {space_id}/space.json
kibob push # Creates/updates spaces in Kibana
kibob togo # Bundles to bundle/spaces.ndjsonEach space definition is stored in its own directory as {space_id}/space.json. For example:
default/space.jsonmarketing/space.jsonengineering/space.json
See the Spaces Guide for complete documentation.
If you have an existing project using the old Bash script:
# Migrate the legacy structure
kibob migrate ./my-project
# Review the migrated manifest
cat default/manifest/saved_objects.json
# Test by pulling from Kibana
kibob pull ./my-projectSee Migration Guide for details.
| Variable | Description | Default |
|---|---|---|
KIBANA_URL |
Kibana base URL | Required |
KIBANA_USERNAME |
Basic auth username | Optional |
KIBANA_PASSWORD |
Basic auth password | Optional |
KIBANA_APIKEY |
API key authentication | Optional |
KIBANA_SPACE |
Default target space used by some workflows | default |
KIBANA_MAX_REQUESTS |
Maximum number of concurrent requests | 8 |
- Issues: https://github.com/VimCommando/kibana-object-manager/issues
- Discussions: https://github.com/VimCommando/kibana-object-manager/discussions
Contributions are welcome. See CONTRIBUTING.md for development setup and guidelines.
Licensed under the Apache License, Version 2.0. See LICENSE for details.