Musoq.CLI is a powerful command-line interface that brings the magic of Musoq to your fingertips. Query various data sources with ease, wherever they reside!
- 🖥️ Spin up a Musoq server
- 🔍 Query diverse data sources
- 🔄 Seamless server-client interaction
- 📊 Multiple output formats (Raw, CSV, JSON, Interpreted JSON, Yaml, Interpreted Yaml)
- 🚫 No additional dependencies required
Powershell:
irm https://raw.githubusercontent.com/Puchaczov/Musoq.CLI/refs/heads/main/scripts/powershell/install.ps1 | iexShell using curl:
curl -fsSL https://raw.githubusercontent.com/Puchaczov/Musoq.CLI/refs/heads/main/scripts/bash/install.sh | sudo bashShell using wget:
wget -qO- https://raw.githubusercontent.com/Puchaczov/Musoq.CLI/refs/heads/main/scripts/bash/install.sh | sudo bashPowershell:
irm https://raw.githubusercontent.com/Puchaczov/Musoq.CLI/refs/heads/main/scripts/powershell/remove.ps1 | iexShell using curl:
curl -fsSL https://raw.githubusercontent.com/Puchaczov/Musoq.CLI/refs/heads/main/scripts/bash/remove.sh | sudo bashShell using wget:
wget -qO- https://raw.githubusercontent.com/Puchaczov/Musoq.CLI/refs/heads/main/scripts/bash/remove.sh | sudo sh- 📥 Install Musoq.CLI using the easy installation script above
- 🖥️ Open any terminal
- 🏃♂️ Run the server in background:
- Windows & Linux:
Musoq serve
- Windows & Linux:
- 🔍 Run queries as needed
- 🛑 To quit the server:
Musoq quit
- 📥 Install Musoq.CLI using the easy installation script above
- 🖥️ Open one terminal and run the server:
- Windows & Linux:
Musoq serve --wait-until-exit
- Windows & Linux:
- 🖥️ Open another terminal
- 🔍 Run a query:
- Windows & Linux:
Musoq run query "select 1 from #system.dual()"
- Windows & Linux:
- 🛑 To quit the server:
Musoq quit
- Quick Reference
- Server Management
- Query Execution - Basics
- Information Retrieval
- Local Configuration
- Advanced Query Features
- Bucket Management
- Python Plugin Management
- Tool Management
- Logging and History
- Base64 Encoding
- Troubleshooting
| Task | Command |
|---|---|
| Run simple query | musoq run "SELECT 1 FROM #system.dual()" |
| Run query as JSON | musoq run "SELECT 1 FROM #system.dual()" --format json |
| Run query as CSV | musoq run "SELECT 1 FROM #system.dual()" --format csv |
| Run query from file | musoq run query.sql |
| Run query with command execution | musoq run "SELECT 1 as Test FROM #system.dual()" --execute "powershell -command 1+2" |
| Process piped text | echo "data" | musoq run "SELECT * FROM #stdin.TextBlock()" |
| Flatten JSON from stdin | echo '{"key":"value"}' | musoq run "SELECT * FROM #stdin.JsonFlat()" |
| Flatten YAML from stdin | echo 'key: value' | musoq run "SELECT * FROM #stdin.YamlFlat()" |
| Convert YAML to JSON | echo 'key: value' | musoq run "SELECT y.Path, y.Value FROM #stdin.YamlFlat() y" --format interpreted_json |
| Convert JSON to YAML | echo '{"key":"value"}' | musoq run "SELECT j.Path, j.Value FROM #stdin.JsonFlat() j" --format yaml |
| Set environment variable | musoq set environment-variable "VAR_NAME" "value" |
| Set agent name | musoq set agent-name "my-agent" |
| List tools | musoq tool list |
| Show tool details | musoq tool show tool-name |
| Execute tool | musoq tool execute tool-name --param1 value1 |
| List Python plugins | musoq python list |
| Create Python plugin | musoq python create plugin_name [template] |
| Read Python plugin | musoq python read plugin_name |
| Rename Python plugin | musoq python update old_name new_name |
| Delete Python plugin | musoq python delete plugin_name |
| Show plugins folder | musoq python folder |
| Get data sources | musoq get data-sources |
| Check server status | musoq get is-running |
| Get environment variables | musoq get environment-variables |
| Create bucket | musoq bucket create bucket-name |
| View query history | musoq log |
| Encode image | musoq image encode file.png |
| Start server | musoq serve |
| Start server (foreground) | musoq serve --wait-until-exit |
| Stop server | musoq quit |
| Format | Flag | Options | Use Case |
|---|---|---|---|
| Table (default) | None or --format table |
--execute |
Human-readable output |
| JSON | --format json |
--execute |
API integration, parsing |
| CSV | --format csv |
--unquoted, --no-header, --execute |
Excel, data analysis |
| Raw | --format raw |
--execute |
Debugging, type inspection |
Note: The --execute option works with all output formats to post-process results with shell commands.
| Template | Use Case |
|---|---|
basic |
Simple data sources with static or computed data |
api |
REST API-based data sources |
| Category | Set Command | Clear Command |
|---|---|---|
| Environment Variable | set environment-variable NAME VALUE |
clear environment-variable NAME |
| Log Path | set log-path PATH |
clear log-path |
| Data Source | Syntax | Example |
|---|---|---|
| System dual | #system.dual() |
SELECT 1 FROM #system.dual() |
| Files | #system.files(path, recursive) |
SELECT Name FROM #system.files('C:\\', false) |
| Directories | #system.directory(path, recursive) |
SELECT Name FROM #system.directory('C:\\', false) |
| Stdin text | #stdin.TextBlock() |
SELECT Value FROM #stdin.TextBlock() |
| Stdin regex | #stdin.Regex(pattern) |
SELECT r.name, r.age FROM #stdin.Regex('(?<name>\w+)\s+(?<age>\d+)') r |
| Stdin JSON | #stdin.JsonFlat() |
SELECT j.Path, j.Value FROM #stdin.JsonFlat() j |
| Stdin YAML | #stdin.YamlFlat() |
SELECT y.Path, y.Value FROM #stdin.YamlFlat() y |
| Python plugin | #schema.datasource() |
SELECT * FROM #mydata.items() |
| Resource | Default Location |
|---|---|
| Settings file | ~/.musoq/settings.json |
| Python plugins | ~/.musoq/Python/Scripts/ |
| Environment variables | ~/.musoq/appsettings.json |
| Tools | ~/.musoq/Tools/ |
Start the local Musoq agent server in the background.
Command (background mode):
musoq serveCommand (foreground mode - wait until exit):
musoq serve --wait-until-exitserve: Starts the local agent API server as a background process. The server handles query execution, plugin management, and all other operations. The command returns immediately after starting the server.serve --wait-until-exit: Starts the server in foreground mode and blocks until the server is explicitly stopped. Useful for debugging or when you want to keep the server running in a terminal session.
Note: Most CLI commands require the server to be running. The server starts automatically when needed in many scenarios.
Gracefully shut down the running server.
Command:
musoq quitExpected Output:
Server shutdown initiated
Execute SQL queries directly from the command line.
Command:
musoq run "select 20001 from #system.dual()"Expected Output:
┌───────┐
│ 20001 │
├───────┤
│ 20001 │
└───────┘
Musoq supports multiple output formats for different use cases.
Command:
musoq run "select 20002 from #system.dual()" --format jsonExpected Output:
[{"20002":20002}]Command:
musoq run "select 20003 from #system.dual()" --format csvExpected Output:
20003
20003
CSV Options:
# Unquoted output (no quotes around string values)
musoq run "select 'text' from #system.dual()" --format csv --unquoted
# No header row
musoq run "select 20003 from #system.dual()" --format csv --no-headerCommand:
musoq run "select 20004 from #system.dual()" --format rawExpected Output:
Columns:
[{"name":"20004","type":"System.Int32","order":0}]
Rows:
[[{"value":20004}]]
Command:
echo '{"name":"Alice","age":30}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
" --format interpreted_jsonExpected Output:
[{"name":"Alice","age":30}]Command:
echo '{"user":{"name":"Alice"}}' | musoq run "
SELECT j.Path as Path, j.Value as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_jsonExpected Output:
{"user":{"name":"Alice"}}Command:
echo '{"name":"Alice","age":30}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
" --format interpreted_yamlExpected Output:
- name: Alice
age: 30Command:
echo '[{"name":"Alice"},{"name":"Bob"}]' | musoq run "
SELECT j.Path as Path, j.Value as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_yamlExpected Output:
- name: Alice
- name: BobExecute simple expressions without requiring FROM clause syntax.
Command:
musoq run "1 + 2"Expected Output:
┌───────┐
│ 1 + 2 │
├───────┤
│ 3 │
└───────┘
Execute SQL queries stored in files for better organization and reusability.
Command:
musoq run path/to/query.sqlExample query.sql:
select 20006 from #system.dual()Expected Output:
┌───────┐
│ 20006 │
├───────┤
│ 20006 │
└───────┘
List all available data sources and their versions.
Command:
musoq get data-sourcesExpected Output:
Name,Version,FullName
api,1.1.0.0,Musoq.Cloud.DataSources.ExternalApi
memorymapped,1.1.0.0,Musoq.Cloud.DataSources.MemoryMapped
system,6.2.15.0,Musoq.DataSources.System
Check the version of the running Musoq server.
Command:
musoq get server-versionExpected Output:
Server version: 1.0.0
List all configured environment variables used by plugins.
Command:
musoq get environment-variablesExpected Output:
Name,Value,Assemblies
TEST_VAR,***cretValue42,"Sample.Tools.Assembly"
API_KEY,***123,"Musoq.Cloud.DataSources.ExternalApi"
Command:
musoq get environment-variables --show-sensitive trueExpected Output:
Name,Value,Assemblies
TEST_VAR,SecretValue42,"Sample.Tools.Assembly"
API_KEY,sk-abc123,"Musoq.Cloud.DataSources.ExternalApi"
Display the path to the environment variables configuration file.
Command:
musoq get environment-variables-file-pathExpected Output:
~/.musoq/appsettings.json
Verify if the Musoq server is currently running.
Command:
musoq get is-runningExpected Output (when running):
Server is up and running
Expected Output (when not running):
Server is not running
Exit codes:
0- Server is running1- Server is not running
Retrieve the port number the server is listening on.
Command:
musoq get server-portExpected Output:
5000
Set environment variables for data source plugins and tools.
Command:
musoq set environment-variable --name "API_TOKEN" --value "secret-token-value"Expected Output:
Environment variable set successfully
Process text data piped from stdin using Musoq queries.
Command:
echo "Line 1
Line 2
Line 3" | musoq run "select s.Value from #stdin.TextBlock() t cross apply t.SplitByNewLines(t.Value) s" --format csvExpected Output:
s.Value
"Line 1"
"Line 2"
"Line 3"
Command:
echo "Short
This is a much longer line of text
Medium line here" | musoq run "select s.Value, Length(s.Value) as Len from #stdin.TextBlock() t cross apply t.SplitByNewLines(t.Value) s where Length(s.Value) > 20" --format csvExpected Output:
s.Value,Len
"This is a much longer line of text",34
Command:
echo "Line 1
Line 2
Line 3" | musoq run "select Count(s.Value) as LineCount from #stdin.TextBlock() t cross apply t.SplitByNewLines(t.Value) s" --format csvExpected Output:
LineCount
3
Extract structured data from text using regex patterns with named capture groups.
Command:
echo "John 30
Alice 25
Bob 35" | musoq run "select r.name, r.age from #stdin.Regex('(?<name>\w+)\s+(?<age>\d+)') r" --format csvExpected Output:
r.name,r.age
"John","30"
"Alice","25"
"Bob","35"
Use unnamed capture groups when you don't need custom column names.
Command:
echo "John 30
Alice 25" | musoq run "select r.column1, r.column2 from #stdin.Regex('(\w+)\s+(\d+)') r" --format csvExpected Output:
r.column1,r.column2
John,30
Alice,25
Find and extract email addresses from text.
Command:
echo "Contact [email protected] for details
Reach out to [email protected]
Email [email protected]" | musoq run "select r.email from #stdin.Regex('(?<email>[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})') r" --format csvExpected Output:
Extract structured information from log file entries.
Command:
echo "2024-01-01 10:30:00 ERROR Something went wrong
2024-01-01 10:31:00 INFO Process started
2024-01-01 10:32:00 WARN Memory low" | musoq run "select r.timestamp, r.level, r.message from #stdin.Regex('(?<timestamp>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+(?<level>\w+)\s+(?<message>.+)') r" --format csvExpected Output:
r.timestamp,r.level,r.message
"2024-01-01 10:30:00",ERROR,Something went wrong
"2024-01-01 10:31:00",INFO,Process started
"2024-01-01 10:32:00",WARN,Memory low
Combine regex extraction with SQL filtering.
Command:
echo "John 30
Alice 25
Bob 35
Charlie 28" | musoq run "select r.name, r.age from #stdin.Regex('(?<name>\w+)\s+(?<age>\d+)') r where ToInt32(r.age) > 28" --format csvExpected Output:
r.name,r.age
"John","30"
"Bob","35"
Find all occurrences of a pattern within text, even multiple matches on the same line.
Command:
echo "The prices are $10.50 and $25.99 today" | musoq run "select r.price from #stdin.Regex('\$(?<price>\d+\.\d+)') r" --format csvExpected Output:
r.price
10.50
25.99
Extract components from URLs using regex.
Command:
echo "Visit https://www.example.com/path
Check http://test.org/page
See https://github.com/user/repo" | musoq run "select r.protocol, r.domain from #stdin.Regex('(?<protocol>https?)://(?<domain>[^/]+)') r" --format csvExpected Output:
r.protocol,r.domain
"https","www.example.com"
"http","test.org"
"https","github.com"
Perform SQL aggregations on extracted data.
Command:
echo "John 30
Alice 25
Bob 35
Charlie 28" | musoq run "select Count(r.name) as TotalCount from #stdin.Regex('(?<name>\w+)\s+(?<age>\d+)') r" --format csvExpected Output:
TotalCount
4
Combine named and unnamed capture groups in the same pattern.
Command:
echo "John 30 Developer
Alice 25 Manager" | musoq run "select r.name, r.column2, r.role from #stdin.Regex('(?<name>\w+)\s+(\d+)\s+(?<role>\w+)') r" --format csvExpected Output:
r.name,r.column2,r.role
|"John","30","Developer"
"Alice","25","Manager"
Note: All extracted values are strings. Use conversion functions like ToInt32(), ToDateTime(), etc., when you need to perform operations requiring specific types.
Flatten JSON structures into path/value pairs for easy querying and manipulation.
Command:
echo '{"user": {"name": "Alice", "age": 30}, "tags": ["dev", "ops"]}' | musoq run "SELECT Path, Value FROM #stdin.JsonFlat() j" --format csvExpected Output:
j.Path,j.Value
"user.name","Alice"
"user.age","30"
"tags[0]","dev"
"tags[1]","ops"
Select specific properties from JSON objects while excluding others.
Command:
echo '{"id":123,"name":"Alice","password":"secret","email":"[email protected]"}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
WHERE j.Path LIKE 'id' OR j.Path LIKE 'name' OR j.Path LIKE 'email'
" --format interpreted_jsonExpected Output:
{"id":123,"name":"Alice","email":"[email protected]"}Filter elements from JSON arrays based on conditions.
Command:
echo '{"items":[0,5,10]}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
WHERE j.Value <> '5'
" --format reconstructed_jsonExpected Output:
{"items":[0,10]}Transform values while maintaining JSON structure.
Command:
echo '{"name":"Alice","age":30,"city":"New York"}' | musoq run "
SELECT j.Path,
CASE WHEN j.Path = 'age' THEN '35' ELSE j.Value END as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_jsonExpected Output:
{"name":"Alice","age":35,"city":"New York"}Remove sensitive data from nested JSON structures.
Command:
echo '{"user":{"name":"Bob","email":"[email protected]","password":"secret123"},"timestamp":"2024-01-01"}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
WHERE j.Path LIKE '%name%' OR j.Path LIKE '%email%' OR j.Path LIKE 'timestamp'
" --format reconstructed_jsonExpected Output:
{"user":{"name":"Bob","email":"[email protected]"},"timestamp":"2024-01-01"}Transform values within arrays.
Command:
echo '{"numbers":[10,20,30]}' | musoq run "
SELECT j.Path,
CASE
WHEN Contains(j.Path, 'numbers[') THEN ToString(ToInt32(j.Value) * 2)
ELSE j.Value
END as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_jsonExpected Output:
{"numbers":[20,40,60]}Work with complex nested structures containing arrays.
Command:
echo '{"users":[{"name":"Alice","scores":[85,90,95]},{"name":"Bob","scores":[70,75,80]}]}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
WHERE j.Path LIKE '%scores%'
" --format csvExpected Output:
j.Path,j.Value
"users[0].scores[0]","85"
"users[0].scores[1]","90"
"users[0].scores[2]","95"
"users[1].scores[0]","70"
"users[1].scores[1]","75"
"users[1].scores[2]","80"
Rename properties while filtering.
Command:
echo '{"user_name":"Alice","user_email":"[email protected]","user_age":30}' | musoq run "
SELECT
CASE
WHEN j.Path = 'user_name' THEN 'name'
WHEN j.Path = 'user_email' THEN 'email'
ELSE j.Path
END as Path,
j.Value
FROM #stdin.JsonFlat() j
WHERE j.Path LIKE 'user_name' OR j.Path LIKE 'user_email'
" --format reconstructed_jsonExpected Output:
{"name":"Alice","email":"[email protected]"}Flatten YAML structures into path/value pairs for easy querying and manipulation.
Command:
echo 'user:
name: Alice
age: 30
tags:
- dev
- ops' | musoq run "SELECT y.Path, y.Value FROM #stdin.YamlFlat() y" --format csvExpected Output:
y.Path,y.Value
"user.name",Alice
"user.age",30
"tags[0]",dev
"tags[1]",ops
Transform YAML data into JSON format using interpreted_json output.
Command:
echo 'user:
name: Alice
age: 30
email: [email protected]
active: true' | musoq run "
SELECT y.Path, y.Value
FROM #stdin.YamlFlat() y
" --format interpreted_jsonExpected Output:
[{"user":{"name":"Alice","age":30,"email":"[email protected]"},"active":true}]Transform JSON data into YAML format.
Command:
echo '{"user":{"name":"Bob","age":25,"email":"[email protected]"},"active":false}' | musoq run "
SELECT j.Path, j.Value
FROM #stdin.JsonFlat() j
" --format yamlExpected Output:
- j.Path: user.name
j.Value: Bob
- j.Path: user.age
j.Value: 25
- j.Path: user.email
j.Value: [email protected]
- j.Path: active
j.Value: falseSelect specific properties from YAML objects while excluding others.
Command:
echo 'id: 123
name: Alice
password: secret
email: [email protected]' | musoq run "
SELECT y.Path, y.Value
FROM #stdin.YamlFlat() y
WHERE y.Path LIKE 'id' OR y.Path LIKE 'name' OR y.Path LIKE 'email'
" --format interpreted_jsonExpected Output:
[{"id":123,"name":"Alice","email":"[email protected]"}]Transform values within YAML arrays.
Command:
echo 'numbers:
- 10
- 20
- 30' | musoq run "
SELECT y.Path,
CASE
WHEN Contains(y.Path, 'numbers[') THEN ToString(ToInt32(y.Value) * 2)
ELSE y.Value
END as Value
FROM #stdin.YamlFlat() y
" --format interpreted_jsonExpected Output:
[{"numbers":[20,40,60]}]Work with complex nested YAML structures containing arrays.
Command:
echo 'users:
- name: Alice
scores:
- 85
- 90
- 95
- name: Bob
scores:
- 70
- 75
- 80' | musoq run "
SELECT y.Path, y.Value
FROM #stdin.YamlFlat() y
WHERE y.Path LIKE '%scores%'
" --format csvExpected Output:
y.Path,y.Value
"users[0].scores[0]",85
"users[0].scores[1]",90
"users[0].scores[2]",95
"users[1].scores[0]",70
"users[1].scores[1]",75
"users[1].scores[2]",80
Transform YAML arrays containing objects into JSON format.
Command:
echo 'users:
- name: Alice
role: Developer
- name: Bob
role: Manager' | musoq run "
SELECT y.Path, y.Value
FROM #stdin.YamlFlat() y
" --format interpreted_jsonExpected Output:
[{"users":[{"name":"Alice","role":"Developer"},{"name":"Bob","role":"Manager"}]}]Perform aggregate operations on flattened YAML.
Command:
echo 'name: Alice
age: 30
city: New York' | musoq run "
SELECT Count(y.Path) as PropertyCount
FROM #stdin.YamlFlat() y
" --format csvExpected Output:
PropertyCount
3
Convert YAML to JSON preserving exact structure using reconstructed_json format.
Command:
echo 'user:
name: Alice
age: 30
email: [email protected]
active: true' | musoq run "
SELECT y.Path as Path, y.Value as Value
FROM #stdin.YamlFlat() y
" --format reconstructed_jsonExpected Output:
{"user":{"name":"Alice","age":30,"email":"[email protected]"},"active":true}Convert JSON to YAML preserving exact structure using reconstructed_yaml format.
Command:
echo '{"user":{"name":"Bob","age":25,"email":"[email protected]"},"active":false}' | musoq run "
SELECT j.Path as Path, j.Value as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_yamlExpected Output:
user:
name: Bob
age: 25
email: [email protected]
active: falseConvert JSON arrays at root level to YAML, preserving array structure.
Command:
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' | musoq run "
SELECT j.Path as Path, j.Value as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_yamlExpected Output:
- name: Alice
age: 30
- name: Bob
age: 25Convert YAML arrays at root level to JSON, preserving array structure.
Command:
echo '- name: Alice
age: 30
- name: Bob
age: 25' | musoq run "
SELECT y.Path as Path, y.Value as Value
FROM #stdin.YamlFlat() y
" --format reconstructed_jsonExpected Output:
[{"name":"Alice","age":30},{"name":"Bob","age":25}]Verify that JSON arrays can be flattened and reconstructed without loss.
Command:
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' | musoq run "
SELECT j.Path as Path, j.Value as Value
FROM #stdin.JsonFlat() j
" --format reconstructed_jsonExpected Output:
[{"name":"Alice","age":30},{"name":"Bob","age":25}]Execute shell commands for each row of query results using template variables. The --execute option allows you to process query output with external commands or scripts.
Command:
musoq run "select 1 as Test from #system.dual()" --execute "powershell -command 1+2"Template variables use the {{ column_name }} syntax to access values from query result columns.
Command:
musoq run "select 'John' as name, 30 as age from #system.dual()" --execute "echo Hello {{ name }}, you are {{ age }} years old" --format csvExpected Output:
name,age,Expression,Result
John,30,"echo Hello John, you are 30 years old","Hello John, you are 30 years old"
- Executes a command template for each row
- Replaces
{{ name }}with "John" and{{ age }}with "30" - Adds the evaluated expression and its result as new columns
- Works only with table and csv format
Command (Windows):
musoq run "select 'test.txt' as filename from #system.dual()" --execute "powershell -command Test-Path {{ filename }}" --format jsonCommand (Linux/macOS):
musoq run "select 'test.txt' as filename from #system.dual()" --execute "test -f {{ filename }} && echo true || echo false" --format jsonCommand:
musoq run "
select s.Value as line
from #stdin.TextBlock() t
cross apply t.SplitByNewLines(t.Value) s
" --execute "echo Processing: {{ line }}" --format csv < input.txt- Reads lines from stdin
- Executes the echo command for each line
- Shows both original data and execution results
Template variables are case-insensitive - {{ Name }}, {{ name }}, and {{ NAME }} all reference the same column.
Command:
musoq run "select 'Alice' as Name from #system.dual()" --execute "echo Hello {{ name }}" --format jsonThe --execute option works with all output formats:
JSON Format:
musoq run "select 'test' as value from #system.dual()" --execute "echo {{ value }}" --format jsonCSV Format:
musoq run "select 'test' as value from #system.dual()" --execute "echo {{ value }}" --format csvTable Format:
musoq run "select 'test' as value from #system.dual()" --execute "echo {{ value }}"Raw Format:
musoq run "select 'test' as value from #system.dual()" --execute "echo {{ value }}" --format rawCommands are executed using the appropriate shell for your platform:
Windows (PowerShell):
musoq run "select 'C:\temp' as path from #system.dual()" --execute "powershell -command Get-ChildItem {{ path }}"Linux/macOS (sh):
musoq run "select '/tmp' as path from #system.dual()" --execute "ls -la {{ path }}"- Variable Substitution: Missing variables in templates remain as
{{ variable_name }}in the output - Error Handling: Command execution errors are captured in the
Resultcolumn - Performance: Commands execute sequentially for each row - consider performance for large datasets
- Shell Syntax: Commands use the native shell syntax for your platform (cmd.exe on Windows, /bin/sh on Linux/macOS)
- Escaping: Values are substituted as-is - be careful with special characters in shell commands
Create a named storage bucket for query results.
Command:
musoq bucket create my-bucketExpected Output:
Bucket 'my-bucket' created successfully
Remove a bucket and its contents.
Command:
musoq bucket delete my-bucketExpected Output:
Bucket 'my-bucket' deleted successfully
Store query results in a bucket for later retrieval.
Step 1: Create the bucket
musoq bucket create my-resultsStep 2: Run query with bucket
musoq run "select 30001 from #system.dual()" --bucket my-resultsExpected Output:
┌───────┐
│ 30001 │
├───────┤
│ 30001 │
└───────┘
Runs a query agains data stored in a specified bucket.
Command:
musoq run "select 20005 from #system.dual()" --bucket test-bucketExpected Output:
┌───────┐
│ 20005 │
├───────┤
│ 20005 │
└───────┘
Note: Python plugins use project-based architecture. Each plugin is a directory containing
main.pyand optional supporting files likerequirements.txt.
View all available Python data source plugin projects.
Command:
musoq python listExpected Output (when no plugins exist):
Name,Description,Created,Modified
Expected Output (with plugins):
Name,Description,Created,Modified
alpha-script,Alpha script for testing,2024-10-21 10:30:00,2024-10-21 10:30:00
beta-script,Beta script for testing,2024-10-21 10:35:00,2024-10-21 10:35:00
Display the contents of a Python plugin project's main.py file.
Command:
musoq python read my_pluginExpected Output:
# Project: my_plugin
# Description: My plugin description
# Created: 2024-10-21 10:30:00
# Modified: 2024-10-21 10:30:00
class DataPlugin:
def schema_name(self):
return "mydata"
# ... rest of plugin code
Create a new Python plugin project from a template.
Command:
musoq python create my_pluginWith specific template:
musoq python create my_plugin basic
musoq python create my_plugin apiExpected Output:
Project 'my_plugin' created successfully from template 'basic'.
~/.musoq/Python/Scripts/my_plugin/
├── main.py # Plugin implementation (from template)
├── requirements.txt # Optional: Python dependencies
└── project.json # Optional: Project metadata
The project folder is automatically opened in your system's default file explorer.
Available templates:
basic(default): Simple data source templateapi: Template for API-based data sources
Plugin structure example (v.2):
"""
Basic Python Plugin Template (v.2)
This template provides the simplest structure for a Musoq Python plugin.
It demonstrates a single data source with basic columns.
SQL Usage:
SELECT * FROM #{schema_name}.items()
SELECT * FROM #{schema_name}.items(10) -- With minimum_id parameter
"""
class DataPlugin:
"""Basic plugin with a single data source."""
def schema_name(self):
"""Return the schema name used in SQL queries: #schema_name.method()"""
return "{schema_name}"
def data_sources(self):
"""Return list of available data source method names."""
return ["items"]
def schemas(self):
"""Return dictionary mapping data source names to their column schemas.
Returns:
dict: {method_name: {column: type, ...}, ...}
"""
return {
"items": {
"id": "int",
"name": "str",
"value": "float",
"active": "bool"
}
}
def initialize(self):
"""Initialize the plugin - called once when plugin is loaded."""
pass
def get_required_env_vars(self, method_name):
"""Return dictionary of environment variables for the specified method.
Args:
method_name: The data source method name
Returns:
dict: Variable name -> is_required (bool)
"""
if method_name == "items":
return {
# "API_KEY": True, # Example: required variable
# "ENDPOINT": False, # Example: optional variable
}
return {}
def get_required_execute_arguments(self, method_name):
"""Return list of parameter definitions for the specified method.
Args:
method_name: The data source method name
Returns:
list: List of (parameter_name, parameter_type) tuples
"""
if method_name == "items":
return [
("minimum_id", "int"), # Optional parameter with default
]
return []
def execute(self, method_name, environment_variables, *args):
"""Execute the specified data source method.
Args:
method_name: The data source method name to execute
environment_variables: Dictionary of environment variables (key-value pairs)
*args: Parameters passed to the method
Yields:
dict: Row data with keys matching the schema
"""
if method_name == "items":
yield from self._get_items(environment_variables, *args)
else:
raise ValueError(f"Unknown method: {method_name}")
def _get_items(self, environment_variables, *args):
"""Generate sample items data.
Args:
environment_variables: Dictionary of environment variables
*args: Optional minimum_id parameter
"""
minimum_id = int(args[0]) if len(args) > 0 else 1
for i in range(minimum_id, minimum_id + 10):
yield {
"id": i,
"name": f"Item {i}",
"value": i * 10.5,
"active": i % 2 == 0
}
def dispose(self):
"""Cleanup resources - called when plugin is unloaded."""
pass
plugin = DataPlugin()Rename an existing Python plugin project.
Command:
musoq python update old_name new_nameExpected Output:
Python project renamed from 'old_name' to 'new_name' successfully
Remove a Python plugin project from the system.
Command:
musoq python delete my_pluginExpected Output:
Python plugin 'my_plugin' deleted successfully
Display or open the Python plugins directory.
Command:
musoq python folderExpected Output:
~/.musoq/Python/Scripts/
Open in file explorer:
musoq python folder --openOpen specific project:
musoq python folder my_plugin --openExecute queries using your custom Python plugins as data sources.
Prerequisite: Create a Python plugin with schema name "mydata" and data sources ["items", "summary"]
Command:
musoq run "select id, name, value from #mydata.items()" --format csvWith parameters:
musoq run "select * from #mydata.items(100)" --format csvMultiple data sources:
musoq run "select * from #mydata.summary()" --format csvExpected Output:
id,name,value
42,"Answer","Meaning"
Note: The server must be restarted after creating a plugin for it to be discovered, or the plugin must exist before server startup.
View all available tools with their metadata.
Command:
musoq tool listExpected Output:
Name,Description,ParameterCount
alpha-tool,Tool for alpha scenarios,2
beta-tool,Secondary analyzer,0
Command:
musoq tool list --search "alpha"Expected Output:
Name,Description,ParameterCount
alpha-tool,Tool for alpha scenarios,2
Display detailed information about a specific tool.
Command:
musoq tool show alpha-toolExpected Output:
Name: alpha-tool
Description: Tool for alpha scenarios
Query: SELECT 10001 FROM #system.dual()
Output Format: json
Parameters:
- firstParam (string) [Required]
Description: Primary value to process
- optionalFlag (bool)
Description: Optional flag controlling execution
Default: enabled
Run a tool with specified parameters.
Command:
musoq tool execute my-tool --debugExpected Output:
Executing query: SELECT 'debug-output' as Result FROM #system.dual()
┌──────────────┐
│ Result │
├──────────────┤
│ debug-output │
└──────────────┘
Command:
musoq tool execute data-processor --param1 "value1" --param2 "value2"Parameter formats:
--param value- Named parameter with value--flag- Boolean flag (sets to true)param value- Positional parameter
Different parameter types require different syntax in the query template:
| Type | Query Syntax | Example |
|---|---|---|
string |
'{{ param }}' |
'{{ path }}' |
int |
{{ param }} |
{{ count }} |
long |
{{ param }} |
{{ size }} |
bool |
{{ param }} |
{{ recursive }} |
float |
{{ param }} |
{{ threshold }} |
Key Rule: String parameters need quotes in SQL, numeric/boolean parameters don't.
Tools are defined as YAML files stored in ~/.musoq/Tools/ directory (e.g., C:\Users\<YourUser>\.musoq\Tools\ on Windows).
File: ~/.musoq/Tools/example-tool.yaml
name: tool-name
description: Brief description of what the tool does
query: |
SELECT
Column1,
'{{ string_param }}' as Text,
{{ numeric_param }} as Number
FROM #datasource.method('{{ path }}', {{ boolean_param }})
WHERE SomeCondition = {{ value }}
ORDER BY Column1 DESC
parameters:
- name: param1
type: string
required: true
description: Description of parameter 1
- name: param2
type: int
required: false
default: 100
description: Description of parameter 2
- name: param3
type: bool
required: false
default: true
description: Description of parameter 3
output:
format: table| Field | Required | Type | Description | Example |
|---|---|---|---|---|
name |
✅ Yes | string | Unique tool identifier (no spaces) | disk-usage |
description |
✅ Yes | string | Brief explanation of tool purpose | Analyze disk usage by file extension |
query |
✅ Yes | string | SQL query with parameter placeholders | See examples below |
parameters |
✅ Yes | array | List of parameter definitions | See parameter format |
output.format |
✅ Yes | string | Output format (table, json, csv) |
table |
Each parameter in the parameters array must have:
- name: parameter_name # Parameter identifier
type: parameter_type # string, int, long, bool, float
required: true/false # Is this parameter mandatory?
default: default_value # Default value (optional params only)
description: help_text # What this parameter doesParameter Types:
string- Text values (use quotes in query:'{{ param }}')int- Integer numbers (no quotes:{{ param }})long- Long integers (no quotes:{{ param }})bool- Boolean values (no quotes:{{ param }})float- Floating point numbers (no quotes:{{ param }})
File: ~/.musoq/Tools/greeting.yaml
name: greeting
description: Display a personalized greeting
query: |
SELECT
'{{ name }}' as Name,
'Hello, {{ name }}!' as Greeting,
{{ age }} as Age
FROM #system.dual()
parameters:
- name: name
type: string
required: true
description: Your name
- name: age
type: int
required: false
default: 0
description: Your age
output:
format: tableUsage:
musoq tool execute greeting -- --name "Alice" --age 30Display recent query execution logs with results.
Command:
musoq logExpected Output (no history):
No query execution logs found
Expected Output (with history):
Recent Query Execution Logs
[2024-10-21 14:30:15] SUCCESS (125ms)
Query: SELECT 1 FROM #system.dual()
Rows: 1
[2024-10-21 14:30:20] SUCCESS (98ms)
Query: SELECT 2 FROM #system.dual()
Rows: 1
[2024-10-21 14:30:25] SUCCESS (103ms)
Query: SELECT 3 FROM #system.dual()
Rows: 1
Control the number of log entries displayed.
Command:
musoq log --count 2Expected Output:
Recent Query Execution Logs (2)
[2024-10-21 14:30:25] SUCCESS (103ms)
Query: SELECT 3 FROM #system.dual()
Rows: 1
[2024-10-21 14:30:20] SUCCESS (98ms)
Query: SELECT 2 FROM #system.dual()
Rows: 1
Query logs include detailed timing information.
Command:
musoq logOutput includes:
- Timestamp:
[2024-10-21 12:34:56]- When the query was executed - Status:
SUCCESSorFAILED- Execution result - Duration:
125ms- How long the query took to execute
Convert image files to base64-encoded strings.
Command:
musoq image encode path/to/image.pngExpected Output:
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==
Command:
musoq image encode path/to/small-file.binExpected Output:
iVBORw0KGgo=
Note: Despite the command name "image encode", it can encode any binary file, not just images.
# Check if server is running
musoq get is-running
# If not running, start it
musoq serve# List available data sources
musoq get data-sources
# For Python plugins, ensure server was restarted after creation
musoq quit
musoq serve# Check recent logs for error details
musoq log --count 5# View environment variables
musoq get environment-variables
# View environment variables file path
musoq get environment-variables-file-path
# Clear and reset an environment variable
musoq clear environment-variable "VAR_NAME"
musoq set environment-variable "VAR_NAME" "new-value"# List all Python plugin projects
musoq python list
# Read plugin content to verify structure
musoq python read plugin_name
# Show plugins directory location
musoq python folder
# Open plugins directory in file explorer
musoq python folder --open