Skip to content

Conversation

@MarioCadenas
Copy link
Contributor

@MarioCadenas MarioCadenas commented Jan 11, 2026

Changes

Overview

This PR adds new AppKit development commands to databricks apps, making them first-class citizens alongside the auto-generated Apps API commands. The implementation follows the same pattern established by the pipelines commands.

New Command Structure

databricks apps now has three command groups:

Group Commands Description
Available Commands deploy, dev-remote, init, logs, run-local, validate Custom development commands
Management Commands create, delete, get, list, start, stop, etc. Auto-generated API commands
Permission Commands get-permissions, set-permissions, etc. Permission management

Key Features

  1. databricks apps init - Initialize new AppKit projects from templates with interactive prompts, but also allowing full prompt override via flags.
  2. databricks apps dev-remote - Run local Vite dev server with WebSocket bridge to remote app (this command already exists, but now has some improvements like deriving the project from the folder and reconnecting).
  3. databricks apps validate - Run validation of the app running type checking, linting and building.
  4. databricks apps deploy - Dual-mode deployment:
    • Bundle mode (when databricks.yml exists): Validates → Deploys bundle → Runs app
    • API mode: Standard API deployment with APP_NAME argument

Directory Structure

cmd/apps/                    # Custom commands
├── apps.go                  # Commands() + ManagementGroupID
├── init.go                  # Initialize projects
├── dev.go                   # Dev-remote command
├── deploy_bundle.go         # Bundle-aware deploy
├── logs.go                  # App logs
├── run_local.go               # Run locally
└── validate.go             # Validate the project compiles

cmd/workspace/apps/          # Auto-generated + overrides
├── apps.go                  # SDK commands
├── overrides.go             # Imports cmd/apps, groups commands
└── errors.go                # Error handling

libs/apps/                   # Shared libraries
├── features/                # Feature definitions
├── prompt/                  # Interactive prompts
├── validation/              # Project validation
└── vite/                    # Vite bridge

Why

Tests

@MarioCadenas MarioCadenas force-pushed the appkit-cli-commands branch 3 times, most recently from 04f4c88 to 6e23dec Compare January 14, 2026 09:01
@eng-dev-ecosystem-bot
Copy link
Collaborator

eng-dev-ecosystem-bot commented Jan 14, 2026

Commit: 6760cdf

Run: 21145314566

Env 🟨​KNOWN 🔄​flaky 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
🟨​ aws linux 7 10 3 411 694 28:19
🟨​ aws windows 10 7 3 413 692 31:13
🟨​ aws-ucws linux 6 14 2 583 568 106:36
🟨​ aws-ucws windows 9 11 2 585 566 97:31
🟨​ azure linux 13 1 4 411 693 34:18
🟨​ azure windows 13 1 4 413 691 31:14
🟨​ azure-ucws linux 4 4 13 3 575 567 91:09
🟨​ azure-ucws windows 7 10 3 581 565 90:48
🟨​ gcp linux 13 1 4 400 699 31:02
🟨​ gcp windows 13 2 1 4 400 697 30:25
30 interesting tests: 22 KNOWN, 6 flaky, 1 SKIP, 1 RECOVERED
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K
🟨​ TestAccept/bundle/deployment/bind/alert 🙈​S 🙈​S 🙈​S 🙈​S 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/deployment/bind/alert/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/deployment/bind/alert/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🔄​ TestAccept/bundle/deployment/bind/pipelines/recreate ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/deployment/bind/pipelines/recreate/DATABRICKS_BUNDLE_ENGINE=terraform ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🟨​ TestAccept/bundle/generate/alert 💚​R 🟨​K 💚​R 🟨​K 🟨​K 🟨​K 💚​R 🟨​K 🟨​K 🟨​K
🟨​ TestAccept/bundle/generate/alert/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 🟨​K 💚​R 🟨​K 🟨​K 🟨​K 💚​R 🟨​K 🟨​K 🟨​K
🟨​ TestAccept/bundle/generate/alert/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 🟨​K 💚​R 🟨​K 🟨​K 🟨​K 💚​R 🟨​K 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/alerts/basic 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/alerts/basic/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/alerts/basic/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/alerts/with_file 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/alerts/with_file/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/alerts/with_file/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K
🔄​ TestAccept/bundle/resources/clusters/deploy/update-after-create ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🟨​K 🟨​K 🟨​K 🟨​K 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🟨​K 🟨​K 🙈​S 🙈​S 🟨​K 🟨​K 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 🟨​K 🟨​K
🟨​ TestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 🟨​K 🟨​K
🔄​ TestAccept/bundle/templates/default-python/combinations/classic ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f
🔄​ TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=no/PY=yes/READPLAN= ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f
💚​ TestAccept/ssh/connection 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 50 slowest tests (at least 2 minutes):
duration env testname
7:58 aws-ucws linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
5:59 aws windows TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:47 gcp windows TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:35 gcp linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:21 aws windows TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
5:13 gcp linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
4:46 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=no/READPLAN=
4:46 gcp windows TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
4:32 aws-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=no/READPLAN=
4:31 aws-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=yes/READPLAN=
4:30 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=yes/PY=yes/READPLAN=
4:28 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=no/READPLAN=1
4:16 azure linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
4:10 aws-ucws windows TestAccept/bundle/resources/experiments/basic/DATABRICKS_BUNDLE_ENGINE=direct
4:06 aws-ucws linux TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=terraform/UV_PYTHON=3.12
4:01 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=no/READPLAN=1
4:01 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:59 azure-ucws windows TestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=direct
3:59 azure-ucws linux TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
3:55 azure-ucws windows TestAccept/bundle/resources/volumes/recreate/DATABRICKS_BUNDLE_ENGINE=direct
3:55 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=no/READPLAN=
3:47 aws-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=yes/READPLAN=
3:40 azure-ucws windows TestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:35 azure-ucws windows TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=terraform/UV_PYTHON=3.9
3:35 azure-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=no/PY=no/READPLAN=
3:29 aws-ucws windows TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=yes/PY=yes/READPLAN=
3:29 azure-ucws linux TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=terraform/UV_PYTHON=3.9
3:27 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:27 aws-ucws windows TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=no/READPLAN=
3:27 aws-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=yes/PY=yes/READPLAN=
3:26 azure-ucws windows TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=direct/UV_PYTHON=3.12
3:26 aws-ucws linux TestAccept/bundle/resources/dashboards/unpublish-out-of-band/DATABRICKS_BUNDLE_ENGINE=direct
3:25 aws-ucws linux TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=direct/UV_PYTHON=3.10
3:24 azure-ucws windows TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=direct/UV_PYTHON=3.9
3:23 azure-ucws linux TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=yes/PY=yes/READPLAN=
3:18 azure-ucws linux TestAccept/bundle/resources/dashboards/change-name/DATABRICKS_BUNDLE_ENGINE=direct
3:17 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:16 aws-ucws windows TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=direct/UV_PYTHON=3.12
3:16 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:14 azure-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=no/PY=no/READPLAN=
3:12 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=yes/READPLAN=1
3:11 aws-ucws linux TestAccept/bundle/resources/dashboards/change-serialized-dashboard/DATABRICKS_BUNDLE_ENGINE=terraform
3:09 aws-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=yes/READPLAN=1
3:09 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:09 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:08 azure-ucws windows TestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=terraform/UV_PYTHON=3.11
3:06 azure-ucws windows TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=yes/READPLAN=
3:06 azure-ucws linux TestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=yes/READPLAN=
3:06 azure-ucws linux TestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:05 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform

@@ -0,0 +1,419 @@
package app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check with @pietern. He wants to unify CLI UX.

Copy link
Contributor

@pietern pietern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking merging. Need to discuss the deps first.

@keugenek keugenek self-requested a review January 16, 2026 12:02
Copy link
Contributor

@arsenyinfo arsenyinfo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those changes duplicate existing entities like template, validation etc and are not in sync with agentic prompts atm. We can't merge it unless there is a unification plan.

@keugenek
Copy link
Contributor

@MarioCadenas
Copy link
Contributor Author

Those changes duplicate existing entities like template, validation etc and are not in sync with agentic prompts atm. We can't merge it unless there is a unification plan.

the idea is to unify yes, but this comes with the approach of having this as humans first, through the apps scope, but of course, many of this should be used by the ai tools

@MarioCadenas
Copy link
Contributor Author

This PR largely duplicates cli aitools already implemented http://github.com/databricks/cli/tree/main/experimental/aitools

Also https://github.com/databricks/appkit/pull/57/changes template - another duplication https://github.com/databricks/cli/tree/main/experimental/aitools/templates/appkit

It has some similar things yes, I already mentioned this, we were doing similar things and we needed to converge into one.
The template is not really a duplication, is a much simpler one that allows configuration and goes into the scope that it should be. With ideally removing the other one

Let's talk about it in the sync

@fjakobs
Copy link
Contributor

fjakobs commented Jan 16, 2026

@arsenyinfo @keugenek this indeed duplicates functionality from aitools tools. The way I see it we are graduating these commands from the internal AI only namespace to fully supported first class commands, which will be used by humans and agents.

We keep the existing tools under aitools tools until the prompts are updated and we no longer need them.

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: fixup

chore: validate command

chore: fixup

chore: remove import command

chore: fixup
@fjakobs
Copy link
Contributor

fjakobs commented Jan 19, 2026

It would be nice to make dev-local an alias to run-local so we have naming consistency between dev-local and run-local

@fjakobs fjakobs temporarily deployed to test-trigger-is January 19, 2026 09:36 — with GitHub Actions Inactive
return fmt.Errorf("failed to run app: %w. Run `databricks apps logs %s` to view logs", err, appName)
}

cmdio.LogString(ctx, "✔ Deployment complete!")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrewnester We'll need to update this after adding a "started" state to apps.

} else {
log.Debugf(ctx, "No validator found for project type, skipping validation")
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of validation happens here that doesn't happen in the regular "bundle deploy"?

We need to be careful not to make this a hard prereq for deployment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is actually to make things better, it runs validation of the app by running linting, typechecking, and building, so it verifies that everything works and the app won't fail to deploy once its running the building process inside the apps process.

Its basically to avoid the annoying behaviour of having to go into databricks or check the logs command to see why the app failed to deploy.

Right now we just have 1 validator for node apps, at some point we will probably have one for python apps too.

But if it doesn't find a validator, then it just keeps going (to avoid introducing breaking changes)


// printAnswered is an alias for internal use.
func printAnswered(title, value string) {
PrintAnswered(title, value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print where? This should use cobra's stdout or stderr from the context or directly.


// runValidationCommand executes a shell command in the specified directory.
func runValidationCommand(ctx context.Context, workDir, command string) *ValidationDetail {
cmd := exec.CommandContext(ctx, "sh", "-c", command)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't work on Windows. Check out libs/exec for something that'll use cmd.exe if needed.

go.mod Outdated
require (
github.com/charmbracelet/huh v0.8.0
github.com/charmbracelet/lipgloss v1.1.0
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fold into the main list above and include the license as a suffix comment.

Also please include in the NOTICE file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the resulting binary size with/without these deps?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Screenshot 2026-01-19 at 17 38 45

After:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants