Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
af340ef
orgs
echarles May 14, 2026
8f90afa
feat: stripe
echarles May 14, 2026
90e2d53
growth kpi
echarles May 15, 2026
bf11e70
sandbox
echarles May 16, 2026
299d242
snapshot
echarles May 16, 2026
4dfaf65
format
echarles May 17, 2026
5f42e06
evals
echarles May 17, 2026
0d6432a
refactor: code sandbox
echarles May 18, 2026
25b3091
evals
echarles May 19, 2026
da73a7b
evals
echarles May 20, 2026
d575197
lint
echarles May 20, 2026
729936b
evals
echarles May 21, 2026
87cb797
wip
echarles May 21, 2026
929cc44
evals
echarles May 21, 2026
c09c92d
evals
echarles May 22, 2026
b829d66
principal
echarles May 23, 2026
8eebd93
evals
echarles May 23, 2026
f888816
evals
echarles May 23, 2026
fb34d5f
evals
echarles May 23, 2026
164cef5
evals
echarles May 23, 2026
a3bbc12
evals
echarles May 23, 2026
57b3cdf
evals
echarles May 24, 2026
f488752
evals
echarles May 25, 2026
e4b324b
evals
echarles May 25, 2026
8012d0a
example: otel
echarles May 26, 2026
ea75a68
feat: userbadge props
echarles May 26, 2026
f0077c9
bump
echarles May 28, 2026
155723d
feat: agent nodes
echarles May 30, 2026
b985da2
membership
echarles May 30, 2026
cde7cf4
principal
echarles May 30, 2026
4c4d3e4
test: usage
echarles May 31, 2026
ff6a984
share
echarles May 31, 2026
70f1d20
select
echarles May 31, 2026
2fb28c0
billable account
echarles Jun 1, 2026
466692c
billable account
echarles Jun 2, 2026
19629c1
cli: cluster
echarles Jun 3, 2026
fec4946
cli: pools
echarles Jun 3, 2026
f8cadf5
ray
echarles Jun 4, 2026
9fe48b2
ray
echarles Jun 4, 2026
8896a99
fix: picker
echarles Jun 5, 2026
6544458
fix: credits
echarles Jun 5, 2026
81976aa
page: principal
echarles Jun 5, 2026
c183279
ray
echarles Jun 6, 2026
34a807d
docs
echarles Jun 6, 2026
c924713
utils
echarles Jun 6, 2026
eba8eff
cache
echarles Jun 6, 2026
3900982
evals
echarles Jun 6, 2026
a37c38a
cli: agents
echarles Jun 7, 2026
cccbab6
bump: versin
echarles Jun 7, 2026
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: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<a href="https://pypi.org/project/datalayer-core/"><img src="https://img.shields.io/pypi/v/datalayer-core.svg" alt="PyPI version"></img></a>
<a href="https://pypi.org/project/datalayer-core/"><img src="https://img.shields.io/pypi/pyversions/datalayer-core.svg" alt="Python versions"></img></a>
<a href="https://github.com/datalayer/core/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-BSD%203--Clause-blue.svg" alt="License"></img></a>
<a href="https://docs.datalayer.app/"><img src="https://img.shields.io/badge/docs-datalayer.app-blue" alt="Documentation"></img></a>
<a href="https://datalayer.ai/docs/"><img src="https://img.shields.io/badge/docs-datalayer.app-blue" alt="Documentation"></img></a>
<a href="https://github.com/datalayer/core/actions/workflows/py-tests.yml"><img src="https://github.com/datalayer/core/actions/workflows/py-tests.yml/badge.svg" alt="Units Tests"></img></a><a href="https://github.com/datalayer/core/actions/workflows/ts-tests.yml"><img src="https://github.com/datalayer/core/actions/workflows/ts-tests.yml/badge.svg" alt="Units Tests"></img></a>
</p>

Expand Down Expand Up @@ -217,10 +217,10 @@ Key platform features accessible through this Client and CLI:

## Documentation

- **Command Line Interface (CLI)**: [https://docs.datalayer.app/cli/](https://docs.datalayer.app/cli/)
- **Command Line Interface (CLI)**: [https://datalayer.ai/docs/cli/](https://datalayer.ai/docs/cli/)
- **Core Python Client**: [core.datalayer.tech/python/](https://core.datalayer.tech/python/)
- **Platform Documentation**: [docs.datalayer.app](https://docs.datalayer.app/)
- **API Reference**: [API documentation](https://docs.datalayer.app/api/)
- **Platform Documentation**: [docs.datalayer.app](https://datalayer.ai/docs/)
- **API Reference**: [API documentation](https://datalayer.ai/docs/api/)

## Development

Expand Down Expand Up @@ -317,7 +317,7 @@ This project is licensed under the [BSD 3-Clause License](https://github.com/dat

## Support

- **Documentation**: [Datalayer Platform Documentation](https://docs.datalayer.app/)
- **Documentation**: [Datalayer Platform Documentation](https://datalayer.ai/docs/)
- **Issues**: [GitHub Issues](https://github.com/datalayer/core/issues)
- **Community**: [Datalayer Platform](https://datalayer.app/)

Expand Down
2 changes: 1 addition & 1 deletion datalayer_core/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

"""Datalayer Core version information."""

__version__ = "1.1.22"
__version__ = "1.1.24"
4 changes: 2 additions & 2 deletions datalayer_core/assets/about.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## About

Datalayer provides a command line tool allowing to list, create, terminate and open a console with runtimes.
Datalayer is a managed AI agents platform for collaborative data analysis, designed to eliminate vendor lock-in.

Read more on https://docs.datalayer.app
Read more on https://datalayer.ai/docs
2 changes: 1 addition & 1 deletion datalayer_core/base/serverapplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Brand(Configurable):
)

docs_url = Unicode(
"https://docs.datalayer.app",
"https://datalayer.ai/docs",
config=True,
help=("Documentation URL."),
)
Expand Down
208 changes: 193 additions & 15 deletions datalayer_core/cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@

"""Command line interface for Datalayer based on Typer."""

import os
import sys

import typer

from datalayer_core.__version__ import __version__
from datalayer_core.cli.commands.about import app as about_app
from datalayer_core.cli.commands.agents import agents_ls
from datalayer_core.cli.commands.agents import app as agents_app
from datalayer_core.cli.commands.agent_nodes import app as agent_nodes_app
from datalayer_core.cli.commands.agent_nodes import agent_nodes_ls
from datalayer_core.cli.commands.authn import (
app as auth_app,
)
Expand All @@ -16,29 +23,35 @@
whoami_root,
)
from datalayer_core.cli.commands.benchmarks import app as benchmarks_app
from datalayer_core.cli.commands.cluster import app as cluster_app
from datalayer_core.cli.commands.config import app as config_app
from datalayer_core.cli.commands.console import app as console_app
from datalayer_core.cli.commands.envs import app as envs_app
from datalayer_core.cli.commands.envs import envs_list, envs_ls
from datalayer_core.cli.commands.envs import envs_ls
from datalayer_core.cli.commands.evals import app as evals_app
from datalayer_core.cli.commands.exec import main as exec_main
from datalayer_core.cli.commands.memberships import app as memberships_app
from datalayer_core.cli.commands.otel import app as otel_app
from datalayer_core.cli.commands.pools import app as pools_app
from datalayer_core.cli.commands.ray import app as ray_app
from datalayer_core.cli.commands.runtime_checkpoints import app as checkpoints_app
from datalayer_core.cli.commands.runtime_checkpoints import (
checkpoints_list,
checkpoints_ls,
)
from datalayer_core.cli.commands.runtime_snapshots import app as snapshots_app
from datalayer_core.cli.commands.runtime_snapshots import snapshots_list, snapshots_ls
from datalayer_core.cli.commands.sandbox_snapshots import app as snapshots_app
from datalayer_core.cli.commands.sandbox_snapshots import snapshots_ls
from datalayer_core.cli.commands.runtimes import app as runtimes_app
from datalayer_core.cli.commands.runtimes import runtimes_list, runtimes_ls
from datalayer_core.cli.commands.runtimes import runtimes_ls
from datalayer_core.cli.commands.secrets import app as secrets_app
from datalayer_core.cli.commands.secrets import secrets_list, secrets_ls
from datalayer_core.cli.commands.secrets import secrets_ls
from datalayer_core.cli.commands.subscription import app as subscription_app
from datalayer_core.cli.commands.subscription import subscription_root
from datalayer_core.cli.commands.tokens import app as tokens_app
from datalayer_core.cli.commands.tokens import tokens_list, tokens_ls
from datalayer_core.cli.commands.tokens import tokens_ls
from datalayer_core.cli.commands.usage import app as usage_app
from datalayer_core.cli.commands.usage import usage_root
from datalayer_core.cli.commands.plans import app as plans_app
from datalayer_core.cli.commands.plans import plans_root
from datalayer_core.cli.commands.users import app as users_app
from datalayer_core.cli.commands.web import app as web_app

Expand Down Expand Up @@ -68,27 +81,124 @@ def main_callback(
is_eager=True,
help="Show version and exit",
),
run_url: str | None = typer.Option(
None,
"--run-url",
help="Override DATALAYER_RUN_URL for this CLI invocation.",
),
iam_url: str | None = typer.Option(
None,
"--iam-url",
help="Override DATALAYER_IAM_URL for this CLI invocation.",
),
runtimes_url: str | None = typer.Option(
None,
"--runtimes-url",
help="Override DATALAYER_RUNTIMES_URL for this CLI invocation.",
),
spacer_url: str | None = typer.Option(
None,
"--spacer-url",
"--space-url",
help="Override DATALAYER_SPACER_URL for this CLI invocation.",
),
library_url: str | None = typer.Option(
None,
"--library-url",
help="Override DATALAYER_LIBRARY_URL for this CLI invocation.",
),
manager_url: str | None = typer.Option(
None,
"--manager-url",
help="Override DATALAYER_MANAGER_URL for this CLI invocation.",
),
ai_agents_url: str | None = typer.Option(
None,
"--ai-agents-url",
help="Override DATALAYER_AI_AGENTS_URL for this CLI invocation.",
),
ai_inference_url: str | None = typer.Option(
None,
"--ai-inference-url",
help="Override DATALAYER_AI_INFERENCE_URL for this CLI invocation.",
),
growth_url: str | None = typer.Option(
None,
"--growth-url",
help="Override DATALAYER_GROWTH_URL for this CLI invocation.",
),
otel_url: str | None = typer.Option(
None,
"--otel-url",
help="Override DATALAYER_OTEL_URL for this CLI invocation.",
),
success_url: str | None = typer.Option(
None,
"--success-url",
help="Override DATALAYER_SUCCESS_URL for this CLI invocation.",
),
status_url: str | None = typer.Option(
None,
"--status-url",
help="Override DATALAYER_STATUS_URL for this CLI invocation.",
),
support_url: str | None = typer.Option(
None,
"--support-url",
help="Override DATALAYER_SUPPORT_URL for this CLI invocation.",
),
mcp_server_url: str | None = typer.Option(
None,
"--mcp-server-url",
help="Override DATALAYER_MCP_SERVER_URL for this CLI invocation.",
),
) -> None:
"""Main callback to handle global options."""
pass
overrides = {
"DATALAYER_RUN_URL": run_url,
"DATALAYER_IAM_URL": iam_url,
"DATALAYER_RUNTIMES_URL": runtimes_url,
"DATALAYER_SPACER_URL": spacer_url,
"DATALAYER_LIBRARY_URL": library_url,
"DATALAYER_MANAGER_URL": manager_url,
"DATALAYER_AI_AGENTS_URL": ai_agents_url,
"DATALAYER_AI_INFERENCE_URL": ai_inference_url,
"DATALAYER_GROWTH_URL": growth_url,
"DATALAYER_OTEL_URL": otel_url,
"DATALAYER_SUCCESS_URL": success_url,
"DATALAYER_STATUS_URL": status_url,
"DATALAYER_SUPPORT_URL": support_url,
"DATALAYER_MCP_SERVER_URL": mcp_server_url,
}
for env_name, value in overrides.items():
if value is not None:
os.environ[env_name] = value.rstrip("/")


# Register commands (without name to add them at the top level)
app.add_typer(about_app)
app.add_typer(agents_app)
app.add_typer(agent_nodes_app)
app.add_typer(auth_app)
app.add_typer(benchmarks_app)
app.add_typer(checkpoints_app)
app.add_typer(cluster_app)
app.add_typer(config_app)
app.add_typer(console_app)
app.add_typer(envs_app)
app.add_typer(evals_app)
app.add_typer(memberships_app)
app.add_typer(otel_app)
app.add_typer(pools_app)
app.add_typer(ray_app)
app.add_typer(runtimes_app)
app.add_typer(secrets_app)
app.add_typer(snapshots_app)
app.add_typer(subscription_app)
app.add_typer(tokens_app)
app.add_typer(users_app)
app.add_typer(usage_app)
app.add_typer(plans_app)
app.add_typer(web_app)

# Add exec command directly to root level
Expand All @@ -99,23 +209,91 @@ def main_callback(
app.command(name="logout")(logout_root)
app.command(name="whoami")(whoami_root)
app.command(name="usage")(usage_root)
app.command(name="plans")(plans_root)
app.command(name="subscription")(subscription_root)

# Add convenient aliases at root level
app.command(name="envs-list")(envs_list)
app.command(name="envs-ls")(envs_ls)
app.command(name="runtimes-list")(runtimes_list)
app.command(name="runtimes-ls")(runtimes_ls)
app.command(name="secrets-list")(secrets_list)
app.command(name="secrets-ls")(secrets_ls)
app.command(name="snapshots-list")(snapshots_list)
app.command(name="snapshots-ls")(snapshots_ls)
app.command(name="checkpoints-list")(checkpoints_list)
app.command(name="checkpoints-ls")(checkpoints_ls)
app.command(name="tokens-list")(tokens_list)
app.command(name="tokens-ls")(tokens_ls)
app.command(name="agent-nodes-ls")(agent_nodes_ls)
app.command(name="agents-ls")(agents_ls)


_GLOBAL_OPTIONS_WITH_VALUES = {
"--run-url",
"--iam-url",
"--runtimes-url",
"--spacer-url",
"--space-url",
"--library-url",
"--manager-url",
"--ai-agents-url",
"--ai-inference-url",
"--growth-url",
"--otel-url",
"--success-url",
"--status-url",
"--support-url",
"--mcp-server-url",
}

_GLOBAL_OPTIONS_NO_VALUES = {
"--version",
}


def _normalize_global_options(argv: list[str]) -> list[str]:
"""Hoist supported global options so they work at any argument position."""
if len(argv) <= 1:
return argv

extracted: list[str] = []
remaining: list[str] = []
i = 1
while i < len(argv):
token = argv[i]

if token == "--":
remaining.extend(argv[i:])
break

if token in _GLOBAL_OPTIONS_NO_VALUES:
extracted.append(token)
i += 1
continue

matched_equals = next(
(
option
for option in _GLOBAL_OPTIONS_WITH_VALUES
if token.startswith(f"{option}=")
),
None,
)
if matched_equals:
extracted.append(token)
i += 1
continue

if token in _GLOBAL_OPTIONS_WITH_VALUES:
extracted.append(token)
if i + 1 < len(argv):
extracted.append(argv[i + 1])
i += 2
else:
i += 1
continue

remaining.append(token)
i += 1

return [argv[0], *extracted, *remaining]


def main() -> None:
"""Main entry point for the Datalayer Typer CLI."""
app()
app(args=_normalize_global_options(sys.argv)[1:])
8 changes: 8 additions & 0 deletions datalayer_core/cli/commands/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
import typer
from rich.console import Console
from rich.markdown import Markdown
from rich.text import Text

# Create a Typer app for the about command
app = typer.Typer()

FOOTER_ANSI = (
"\n"
"\033[0;32m☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷☷\033[0m "
"\033[1;93m☰ DATA\033[0m\033[1;92mLAYER\033[0m"
)


@app.command()
def about() -> None:
Expand All @@ -24,6 +31,7 @@ def about() -> None:
with open(about_file_path) as readme:
markdown = Markdown(readme.read())
console.print(markdown)
console.print(Text.from_ansi(FOOTER_ANSI))
except FileNotFoundError:
console.print(f"[red]Error: Could not find about.md at {about_file_path}[/red]")
raise typer.Exit(1)
Expand Down
Loading
Loading