This is an automated email from the ASF dual-hosted git repository.
psiace pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal-oli.git
The following commit(s) were added to refs/heads/main by this push:
new f74cb15 feat: add Apache OpenDAL Oli skill for direct data operations
(#18)
f74cb15 is described below
commit f74cb15ee00e07f422455ff36ac7128784c55f16
Author: Chojan Shang <[email protected]>
AuthorDate: Tue Feb 24 11:29:20 2026 +0800
feat: add Apache OpenDAL Oli skill for direct data operations (#18)
* feat: add Apache OpenDAL Oli skill for direct data operations
* docs(skill): fix oli --config option placement examples
* docs(skill): split profile setup reference and refine env-mode rules
* skill: rename to oli and address PR review comments
---
skills/oli/SKILL.md | 108 ++++++++++++++++++++
skills/oli/agents/openai.yaml | 4 +
skills/oli/references/commands.md | 68 +++++++++++++
skills/oli/references/profile-setup.md | 85 ++++++++++++++++
skills/oli/references/safety-troubleshooting.md | 130 ++++++++++++++++++++++++
5 files changed, 395 insertions(+)
diff --git a/skills/oli/SKILL.md b/skills/oli/SKILL.md
new file mode 100644
index 0000000..afb381a
--- /dev/null
+++ b/skills/oli/SKILL.md
@@ -0,0 +1,108 @@
+---
+name: oli
+description: Direct command playbooks for Apache OpenDAL Oli CLI data access
and mutation. Use when Codex must run real `oli` commands to list, read, copy,
move, delete, edit, stream, or benchmark data across local paths and
`profile:/path` locations.
+---
+
+# Apache OpenDAL Oli
+
+## Command Principles
+
+- Prefer direct command execution over abstract planning.
+- Run read-only checks before mutating data.
+- Use explicit paths and explicit profile source selection (config-file mode
or environment mode).
+
+## Direct Command Playbooks
+
+### Inspect Data Without Mutation
+
+```bash
+oli ls 's3:/warehouse/'
+oli ls -r 's3:/warehouse/2026/'
+oli ls -T 's3:/warehouse/'
+oli stat 's3:/warehouse/events.parquet'
+oli cat 's3:/warehouse/schema.json'
+```
+
+### Copy Local File To Remote
+
+```bash
+oli cp ./events.parquet 's3:/ingest/events.parquet'
+oli stat 's3:/ingest/events.parquet'
+```
+
+### Copy Remote File To Local
+
+```bash
+oli cp 's3:/ingest/events.parquet' ./events.parquet
+```
+
+### Copy Across Profiles
+
+```bash
+oli cp 's3:/warehouse/events.parquet' 'r2:/backup/events.parquet'
+oli stat 'r2:/backup/events.parquet'
+```
+
+### Recursive Directory Copy
+
+```bash
+oli ls -r 's3:/warehouse/2026/'
+oli cp -r 's3:/warehouse/2026/' 'r2:/backup/2026/'
+oli ls -r 'r2:/backup/2026/'
+```
+
+### Move File Or Directory
+
+```bash
+oli mv 's3:/staging/events.parquet' 's3:/warehouse/events.parquet'
+oli mv -r 's3:/staging/old-batch/' 's3:/archive/old-batch/'
+```
+
+### Safe Recursive Delete
+
+```bash
+oli ls -r 's3:/staging/to-delete/'
+oli rm -r 's3:/staging/to-delete/'
+oli ls 's3:/staging/'
+```
+
+### Stream Input To Object
+
+```bash
+printf '%s\n' '{"status":"ok"}' | oli tee 's3:/logs/healthcheck.json'
+```
+
+### Edit Remote File
+
+```bash
+EDITOR=vim oli edit 's3:/docs/README.md'
+```
+
+### Run Benchmark Suite
+
+```bash
+oli bench --config ./config.toml s3 ./suite.toml
+```
+
+## Hard Rules
+
+- Always use `profile:/path` syntax and avoid `://`.
+- Use `profile:/path` for remote targets and plain paths for local filesystem
targets.
+- For directory-level mutations, explicitly use `-r` and inspect scope first.
+- For delete operations, list first, delete second, verify third.
+- For cross-profile copy and move, verify source and destination with `stat`
or `ls`.
+- In config-file mode, pass `--config <path>` explicitly.
+- In environment-variable mode, do not pass `--config`.
+
+## Failure Triage
+
+- `unknown profile`: check profile name and `config.toml`.
+- `missing 'type' in profile`: add profile `type`.
+- `Host part in a location is not supported`: replace `://` with `:/`.
+- Recursive command errors: confirm `-r` and target kind (file vs directory).
+
+## Resource Navigation
+
+- Read `references/profile-setup.md` for config-file mode vs
environment-variable mode.
+- Read `references/commands.md` for command semantics and flags.
+- Read `references/safety-troubleshooting.md` for risk control and debugging.
diff --git a/skills/oli/agents/openai.yaml b/skills/oli/agents/openai.yaml
new file mode 100644
index 0000000..3b6857e
--- /dev/null
+++ b/skills/oli/agents/openai.yaml
@@ -0,0 +1,4 @@
+interface:
+ display_name: "Apache OpenDAL Oli"
+ short_description: "Direct command playbooks for Apache OpenDAL Oli CLI"
+ default_prompt: "Use $oli to execute real Apache OpenDAL Oli CLI commands
for data access and mutation."
diff --git a/skills/oli/references/commands.md
b/skills/oli/references/commands.md
new file mode 100644
index 0000000..6832a13
--- /dev/null
+++ b/skills/oli/references/commands.md
@@ -0,0 +1,68 @@
+# OLI Command Reference
+
+## Location Semantics
+
+- Use local filesystem mode when the argument does not contain `:/`.
+- Use remote profile mode when the argument is `<profile>:/<path>`.
+- OLI locations use `profile:/path` syntax, not URL syntax.
+
+Examples:
+
+```bash
+# local path
+oli ls './data/'
+
+# remote path
+oli ls 's3:/data/'
+
+# URL-style syntax (not interpreted as profile location)
+oli ls 's3://data/'
+```
+
+## Profile Setup
+
+For profile source modes, config examples, and `--config` usage rules, read:
+
+- `references/profile-setup.md`
+
+## Commands
+
+### Read-Only
+
+- `oli ls <target>`
+- `oli ls -r <target>`
+- `oli ls -T <target>`
+- `oli cat <target>`
+- `oli stat <target>`
+- `oli config view`
+
+### Mutating
+
+- `oli cp <source> <destination>`
+- `oli cp -r <source_dir> <destination_dir>`
+- `oli cp --content-type application/json <source> <destination>`
+- `oli mv <source> <destination>`
+- `oli mv -r <source_dir> <destination_dir>`
+- `oli rm <target>`
+- `oli rm -r <target_dir>`
+- `oli tee <destination>`
+- `oli tee -a <destination>`
+- `oli edit <target>`
+
+### Benchmark
+
+- `oli bench <profile> <suite.toml>`
+
+## Binary Aliases
+
+`oli` supports executable-name aliases:
+
+- `obench` -> `bench`
+- `ocat` -> `cat`
+- `ocp` -> `cp`
+- `ols` -> `ls`
+- `orm` -> `rm`
+- `ostat` -> `stat`
+- `omv` -> `mv`
+
+Prefer `oli <subcommand>` for clarity unless alias behavior is explicitly
required.
diff --git a/skills/oli/references/profile-setup.md
b/skills/oli/references/profile-setup.md
new file mode 100644
index 0000000..9d2544b
--- /dev/null
+++ b/skills/oli/references/profile-setup.md
@@ -0,0 +1,85 @@
+# OLI Profile Setup
+
+## Overview
+
+Use one profile source mode per shell/session:
+
+- Config-file mode: define profiles in TOML and pass `--config`.
+- Environment-variable mode: define profiles in `OLI_PROFILE_*` and do not
pass `--config`.
+
+## Config Resolution
+
+- Default config path:
+ - Linux: `~/.config/oli/config.toml`
+ - macOS: `~/Library/Application Support/oli/config.toml`
+ - Windows: `%APPDATA%\oli\config.toml`
+- Environment variables override file configuration.
+- Environment key format: `OLI_PROFILE_<PROFILE>_<OPTION>`
+
+## Mode A: Config-File Profiles
+
+Use `--config` as a subcommand option (not a top-level global option).
+
+Example `config.toml` with `s3` and `r2`:
+
+```toml
+[profiles.s3]
+type = "s3"
+bucket = "my-bucket"
+region = "us-east-1"
+endpoint = "https://s3.amazonaws.com"
+access_key_id = "..."
+secret_access_key = "..."
+root = "/workspace-s3"
+
+[profiles.r2]
+type = "s3"
+bucket = "my-bucket"
+region = "auto"
+endpoint = "https://<account_id>.eu.r2.cloudflarestorage.com"
+access_key_id = "..."
+secret_access_key = "..."
+root = "/workspace-r2"
+```
+
+Run:
+
+```bash
+oli ls --config ./config.toml 's3:/'
+oli cp --config ./config.toml 's3:/a.txt' 'r2:/a.txt'
+```
+
+## Mode B: Environment Variable Profiles
+
+Define both profiles with `OLI_PROFILE_*`, then run commands without
`--config`.
+
+```bash
+export OLI_PROFILE_S3_TYPE=s3
+export OLI_PROFILE_S3_BUCKET=my-bucket
+export OLI_PROFILE_S3_REGION=us-east-1
+export OLI_PROFILE_S3_ENDPOINT=https://s3.amazonaws.com
+export OLI_PROFILE_S3_ACCESS_KEY_ID=...
+export OLI_PROFILE_S3_SECRET_ACCESS_KEY=...
+export OLI_PROFILE_S3_ROOT=/workspace-s3
+
+export OLI_PROFILE_R2_TYPE=s3
+export OLI_PROFILE_R2_BUCKET=my-bucket
+export OLI_PROFILE_R2_REGION=auto
+export OLI_PROFILE_R2_ENDPOINT=https://<account_id>.eu.r2.cloudflarestorage.com
+export OLI_PROFILE_R2_ACCESS_KEY_ID=...
+export OLI_PROFILE_R2_SECRET_ACCESS_KEY=...
+export OLI_PROFILE_R2_ROOT=/workspace-r2
+```
+
+Run:
+
+```bash
+oli ls 's3:/'
+oli cp 's3:/data.txt' 'r2:/backup/data.txt'
+```
+
+## Common Pitfalls
+
+- Do not use `://` in locations; use `profile:/path`.
+- In environment-variable mode, do not pass `--config`.
+- In config-file mode, pass a valid TOML file with `[profiles.*]`.
diff --git a/skills/oli/references/safety-troubleshooting.md
b/skills/oli/references/safety-troubleshooting.md
new file mode 100644
index 0000000..6dd36b3
--- /dev/null
+++ b/skills/oli/references/safety-troubleshooting.md
@@ -0,0 +1,130 @@
+# OLI Safety And Troubleshooting
+
+## Safe Execution Checklist
+
+1. Resolve intent:
+- `read-only` for inspection
+- `mutating` for data changes
+
+2. Validate source and destination paths with read-only checks:
+
+```bash
+oli ls 's3:/path/'
+oli stat 's3:/path/to/object'
+```
+
+3. Execute mutation only after verification:
+
+```bash
+oli cp 's3:/path/to/object' 'r2:/backup/object'
+```
+
+4. Verify result:
+
+```bash
+oli stat 'r2:/backup/object'
+```
+
+## High-Risk Operations
+
+### Recursive Delete
+
+- Always inspect scope before `rm -r`.
+
+```bash
+oli ls -r 's3:/staging/prefix/'
+oli rm -r 's3:/staging/prefix/'
+oli ls 's3:/staging/'
+```
+
+### Recursive Move
+
+- `mv -r` moves data and deletes source entries afterward.
+- Validate source and destination roots before running.
+
+### Recursive Copy
+
+- Use `cp -r` only for directory-level workflows.
+- Confirm destination is a directory or a new path intended as directory root.
+
+## Common Errors And Fixes
+
+### `unknown profile: <name>`
+
+Cause:
+- Profile name missing in config and environment.
+
+Fix:
+- Add `[profiles.<name>]` in `config.toml`, or set `OLI_PROFILE_<NAME>_TYPE`.
+- Use `oli config view` to inspect available profiles.
+
+### `missing 'type' in profile`
+
+Cause:
+- Profile exists but has no `type` key.
+
+Fix:
+- Add `type = "<service>"` in the profile table.
+
+### `Host part in a location is not supported`
+
+Cause:
+- Used `://` instead of `:/`.
+
+Fix:
+- Replace `s3://a/b` with `s3:/a/b`.
+
+### `can not move a directory in non-recursive mode`
+
+Cause:
+- Tried to move directory with `mv` without `-r`.
+
+Fix:
+- Use `mv -r`.
+
+### `Recursive copy destination '...' exists but is not a directory`
+
+Cause:
+- `cp -r` destination points to an existing file.
+
+Fix:
+- Use a directory destination path.
+
+### `No configuration profiles found in ...`
+
+Cause:
+- Config file missing or empty at the selected `--config` path.
+
+Fix:
+- Create config file with at least one profile.
+
+### `TOML parse error ... missing field profiles`
+
+Cause:
+- `--config` points to an invalid or empty TOML file.
+- In environment-variable mode, `--config` was passed unintentionally.
+
+Fix:
+- In config-file mode, pass a valid config file containing `[profiles.*]`.
+- In environment-variable mode, do not pass `--config`.
+
+## Operational Patterns
+
+### Cross-Profile Transfer
+
+```bash
+oli cp 's3:/dataset/part-0001.parquet' 'r2:/archive/part-0001.parquet'
+oli stat 'r2:/archive/part-0001.parquet'
+```
+
+### Controlled Metadata Check
+
+```bash
+oli stat 's3:/dataset/part-0001.parquet'
+```
+
+Use the output to validate:
+- `size`
+- `etag` (if available)
+- `content-type`
+- `last-modified`