Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .agents/skills/espipe/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,12 @@ For Elasticsearch outputs, configuration options are available before bulk inges

- `--pipeline <path>` installs a JSON or YAML ingest pipeline
- `--pipeline-name <name>` overrides the pipeline name; `_none` disables a request-level default when compatible
- `--template <path>` installs a composable index template from JSON, JSONC, JSON5, YAML, or YML
- `--template-name <name>` overrides the template name
- `--template-overwrite=true|false` controls replacement of an existing template
- `--template <path|_name>` installs a file-backed composable index template or selects a template compiled into espipe
- `--template _okf` selects the bundled Open Knowledge Format v0.2 mapping; its default Elasticsearch name is `open-knowledge-format`
- `--template-name <name>` overrides a file-derived or bundled default template name
- `--template-overwrite=true|false` controls file-template replacement and bundled-template pattern updates

Bundled templates read their selected Elasticsearch template before ingestion. A missing template is created with the target index in `index_patterns`. An existing template gains the exact target index when absent while preserving its stored body. With `--template-overwrite=false`, a missing bundled template uses create-only semantics, an existing exact target proceeds without a write, and an existing template missing the exact target fails. Keep bundled-template preflight serial when separate processes add indices because concurrent read and update cycles are last-write-wins.

Pipeline and template preflight errors abort before bulk ingestion starts. These options require an Elasticsearch output.

Expand All @@ -90,6 +93,7 @@ Examples:
- `espipe accounts.csv records:customers`
- `espipe users.csv https://host:9200/users`
- `espipe --action upsert --generate-id=true 'docs/**/*.md' env:/documents`
- `espipe 'knowledge/**/*.md' env:/knowledge --template _okf --content markdown`
- `espipe --split /hits response.json output.ndjson`

Use only flags the user requests or that are required to express the destination. Do not reinterpret `--action index` as an overwrite-by-source-ID option; IDs are used only when explicit or generated according to the rules above.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added `.env` fallback for missing `ELASTIC_ES_URL` and `ELASTIC_ES_API_KEY` settings used by `env:/` outputs.
- Added the bundled `_okf` Elasticsearch template with explicit Open Knowledge Format v0.2 mappings, shared index-pattern maintenance, and `--template-name` overrides.

### Changed

Expand Down
52 changes: 52 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ include = [
"CHANGELOG.md",
"LICENSE.md",
"README.md",
"assets/templates/*.yaml",
"src/**/*.rs",
"tests/**/*.rs",
"tests/fixtures/anydoc/*",
Expand All @@ -41,6 +42,7 @@ futures = "^0.3.34"
glob = "^0.3.4"
log = "^0.4.33"
reqwest = { version = "^0.13.4", features = ["blocking"] }
rust-embed = "^8.7.2"
serde_json = { version = "^1.0.151", features = ["arbitrary_precision", "raw_value"] }
serde = { version = "^1.0.229", features = ["derive"] }
yaml_serde = "^0.10.7"
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,22 @@ Elasticsearch requests use gzip compression by default. `espipe` retries `429 To

`400 Bad Request` bulk responses are logged and counted as zero successful documents for that batch.

#### Index templates

`--template` accepts a JSON, JSONC, JSON5, YAML, or YML composable index template file. A value beginning with `_` selects a template compiled into `espipe` instead. File-backed templates keep their own `index_patterns`; a mismatch with the output index produces a warning.

The bundled `_okf` template maps Open Knowledge Format v0.2 metadata and the `content.body`, `content.markdown`, and `origin` fields emitted by local document ingestion. Official identifiers and categorical metadata use `keyword`, prose uses `text`, timestamps use `date`, and repeated source, verifier, and parameter records use `nested`. Automatic date detection is disabled. Unknown strings become one `keyword` field with `ignore_above: 2048`, without a `text` plus `keyword` multifield.

```bash
espipe 'knowledge/**/*.md' env:/team-knowledge --template _okf --content markdown
```

`_okf` installs as `open-knowledge-format` by default. Use `--template-name team-okf` to select another cluster-side name. On each run, `espipe` reads that template. If it does not exist, `espipe` creates it with the output index in `index_patterns`. If it exists, `espipe` appends the exact output index when absent and writes the stored template body back without replacing its mappings, settings, aliases, priority, version, metadata, or component references. An existing wildcard does not suppress the exact index entry.

`--template-overwrite=false` uses create-only semantics when the selected template is absent. It accepts an existing template only when the exact output index is already listed. Reading and writing bundled templates requires the corresponding Elasticsearch index-template privileges.

Concurrent processes can lose one another's appended index because Elasticsearch has no atomic index-pattern append operation. Run bundled-template preflight serially when separate processes target new indices. An overridden name should identify a template dedicated to that bundled asset; selecting an unrelated template broadens its index coverage.

Local import summaries separate discovered files from documents: `Piped 5,850 of 5,850 docs from 6,246 files ...`. Skipped files count as files, not documents.

### File and stdout output
Expand Down
124 changes: 124 additions & 0 deletions assets/templates/_okf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
index_patterns: []
_meta:
description: Open Knowledge Format v0.2 documents
okf_version: "0.2"
espipe:
template_revision: 1
default_template_name: open-knowledge-format
template:
mappings:
date_detection: false
dynamic_templates:
- unknown_strings:
match_mapping_type: string
mapping:
type: keyword
ignore_above: 2048
properties:
content:
properties:
type:
type: keyword
title:
type: text
description:
type: text
resource:
type: keyword
ignore_above: 2048
tags:
type: keyword
ignore_above: 2048
okf_version:
type: keyword
status:
type: keyword
stale_after:
type: date
runtime:
type: keyword
ignore_above: 2048
computation:
type: keyword
ignore_above: 2048
body:
type: text
markdown:
type: text
sources:
type: nested
properties:
id:
type: keyword
ignore_above: 2048
resource:
type: keyword
ignore_above: 2048
title:
type: text
author:
type: keyword
ignore_above: 2048
usage_count:
type: long
last_modified:
type: date
usage_window:
properties:
from:
type: date
to:
type: date
usage_window:
properties:
from:
type: date
to:
type: date
generated:
properties:
by:
type: keyword
ignore_above: 2048
at:
type: date
verified:
type: nested
properties:
by:
type: keyword
ignore_above: 2048
at:
type: date
parameters:
type: nested
properties:
name:
type: keyword
type:
type: keyword
required:
type: boolean
executor:
properties:
resource:
type: keyword
ignore_above: 2048
receipt:
type: keyword
ignore_above: 2048
attester:
properties:
resource:
type: keyword
ignore_above: 2048
origin:
properties:
scheme:
type: keyword
path:
type: keyword
ignore_above: 2048
filename:
type: keyword
ignore_above: 2048
4 changes: 2 additions & 2 deletions examples/steam-games/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ Then run from the repository root directory against a new `steam-games` index. I
```bash
espipe ~/Downloads/steam-games-dataset-march-2026/games.csv \
http://localhost:9200/steam-games \
--pipeline examples/steam-games/steam-games-pipeline.yml \
--pipeline examples/steam-games/steam-games-pipeline.yaml \
--pipeline-name steam-games \
--template examples/steam-games/steam-games-template.yml
--template examples/steam-games/steam-games-template.yaml
```

The pipeline splits comma-delimited `Tags` and `Screenshots` values into arrays and converts `Windows`, `Mac`, and `Linux` from title-case strings into booleans.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-08-26
Loading