tom_d4rt_dcli
Builds on `tom_d4rt` and adds dcli shell-scripting, VS Code, and chat bridges plus a base REPL. The extensible foundation for analyzer-based D4rt command-line tools.
Overview
From the module readme.md file:
What it enables
Enables dcli shell scripting, base REPL for tools, stacked D4rt CLIs.
Relationships
Standalone — no declared relationships.
tom_d4rt_dcli
> Attribution. The tom_d4rt project is an extended clone of the original > d4rt project by Moustapha Kodjo Amadou, initially published in 2025. The > complete interpreter is based on his idea.
Analyzer-based D4rt CLI with dcli shell-scripting bridges — the extensible foundation for building D4rt command-line tools.
Overview
tom_d4rt_dcli is the analyzer-based base layer of the D4rt CLI ecosystem. It sits directly on top of
tom_d4rt (the Dart-analyzer-powered sandboxed interpreter) and adds:
-
Full dcli shell-scripting bridges (
dcli,dcli_core,dcli_terminal) - VS Code scripting-API bridges (
tom_vscode_scripting_api) - Telegram / chat integration bridges (
tom_chattools) - An abstract base REPL class (
D4rtReplBase) that downstream tool packages extend - A ready-to-run concrete REPL (
DcliRepl) exposed as thedcliexecutable
The package is the shared nucleus of the stacked-REPL design used across the Tom workspace:
dcli (DcliRepl in this package, bin/dcli.dart)
└── tom_dartscript_bridges (binary: d4rt — adds full Tom Framework bridges)
└── tom_build_cli (binary: tom — adds build/workspace bridges)
Source-based vs analyzer-free — which D4rt family
D4rt ships in two execution families, and tom_d4rt_dcli belongs to the first:
- Source-based (analyzer) —
tom_d4rt,tom_d4rt_dcli,
tom_d4rt_flutter. Parses Dart source with the analyzer, giving full type inference and precise error reporting. This is the
stable reference and usually the preferable choice. - Analyzer-free (mirror AST)
— tom_d4rt_ast, tom_ast_model, tom_ast_generator, tom_d4rt_exec,
tom_dcli_exec, tom_d4rt_flutter_ast. Runs from pre-compiled
SAstNode trees with no analyzer dependency, which makes it viable on the
web (the analyzer is too large to ship there) and for on-the-fly / OTA updates. It is a complete alternative, but because generated AST bundles are large, the source-based interpreter is usually preferable unless the web/OTA constraint applies.
tom_d4rt_dcli requires the Dart analyzer (via tom_d4rt) to resolve and execute scripts. Its
analyzer-free twin is tom_dcli_exec, built on
tom_d4rt_exec. Both packages expose the same D4rtReplBase / DcliRepl
surface and the same dcli executable — they differ only in the underlying execution engine — so a tool written against one ports to the other by swapping the dependency.
---
Installation
Add to your pubspec.yaml:
dependencies:
tom_d4rt_dcli: ^1.1.6
Or via the command line:
dart pub add tom_d4rt_dcli
dcli executable
The package ships a bin/dcli.dart entry point. After adding the dependency you can run the REPL directly through
dart run:
dart run tom_d4rt_dcli:dcli
In downstream tool packages that compile the binary, the entry point is:
import 'package:tom_d4rt_dcli/tom_d4rt_dcli.dart';
Future<void> main(List<String> arguments) async {
await DcliRepl().run(arguments);
}
---
Features
dcli shell-scripting bridges
Scripts executed inside the REPL or passed as files have transparent access to the full dcli API family:
| Package | Bridge class | Notable bridged types |
|---|---|---|
dcli |
PackageDcliBridge |
Ask
,
Confirm
,
FetchUrl
,
DartScript
,
DartSdk
,
Settings
,
Shell
,
DCliPaths
,
FileSyncFile
,
NamedLock
,
PubCache
,
ProcessDetails
,
Remote
|
dcli_core |
PackageDcliCoreBridge |
Cat
,
Env
,
Find
,
FindItem
,
FindConfig
,
Which
,
DCliPlatform
,
LineFile
,
RunException
|
dcli_terminal |
PackageDcliTerminalBridge |
Ansi
,
AnsiColor
,
Format
,
Terminal
,
TableAlignment
|
Scripts can use the standard dcli idioms directly in D4rt:
import 'package:dcli/dcli.dart';
// File operations
touch('output.txt', create: true);
'output.txt'.write('Hello from D4rt!');
final lines = read('output.txt').toList();
copy('output.txt', 'backup.txt');
// Process execution
'git status'.run;
final result = 'ls -la'.toList();
// Environment
final home = env['HOME'];
if (isOnPATH('dart')) print('Dart is available');
VS Code scripting-API bridge
The PackageTomVscodeScriptingApiBridge exposes tom_vscode_scripting_api classes to scripts running inside the interpreter, including
VSCodeBridgeClient, LazyVSCodeBridgeAdapter, VSCodeBridgeResult,
VSCode, VSCodeCommands, VSCodeCommonCommands, VSCodeWindow,
VSCodeWorkspace, VSCodeChat, VSCodeExtensions, VSCodeLanguageModel,
LanguageModelChat, LanguageModelChatMessage, ChatParticipant,
ChatRequest, and related types.
Telegram / chat bridge
The PackageTomChattoolsBridge bridges tom_chattools types — ChatConfig,
ChatMessage, ChatSender, ChatAttachment, ChatResponse,
ChatReceiver, ChatApi, ChatMessageFilter, and TelegramChatConfig
— making them usable inside D4rt scripts without any native Dart compilation.
REPL features
Multiline input modes — enter blocks spanning multiple lines:
| Command | Mode |
|---|---|
.start-define | Define functions/classes (persist in session) |
.start-script | Execute block with return value |
.start-file | Run in current REPL environment |
.start-execute | Run as isolated fresh program |
.start-vscode-eval | Evaluate in connected VS Code bridge |
.start-vscode-script | Execute full script in VS Code bridge |
.end | Finish and execute the current block |
Persistent command history — history is stored to ~/.tom/dcli/.history (up to 500 lines) and reloaded on the next REPL startup. Arrow-key navigation is provided by
dart_console.
Sessions — all interactive input is recorded to ~/.tom/dcli/<session-id>.session.txt
and replayed on resume:
dcli -session mywork # start or resume a named session
dcli -replace-session mywork # delete session and start fresh
dcli -list-sessions # list available sessions
Replay files — pre-written .dcli (or .replay.txt) files can be loaded interactively or executed headlessly:
dcli setup.dcli # execute replay file and exit
dcli -run-replay setup.dcli # same, explicit flag
dcli -run-replay tests.dcli -test # test mode (verifies assertions)
dcli -replay warmup.dcli -session main # replay into a named session
dcli -replay warmup.dcli # replay before starting REPL
Bot mode — run the REPL as a Telegram bot server. Commands are received from authorised Telegram users, executed against the D4rt interpreter, and results are returned as formatted messages:
dcli --bot-mode --bot-config bot.yaml
Bot-mode configuration (BotModeConfig) is loaded from a YAML file and supports multiple bots, per-bot VS Code server connections, command whitelists/blacklists, directory allow/block lists, execution time/output-size limits, file-transfer policies, and Telegram message formatting options.
stdin execution — pipe code directly:
echo 'print(42);' | dcli --stdin
cat my_script.dart | dcli --stdin
echo 'return 5 + 6;' | dcli --stdin # exit code = result
Init source — place a dcli_init_source.dart file in ~/.tom/dcli/
to auto-import packages or declare globals before every session.
Command aliases (defines) — create shorthand aliases with argument placeholders:
define greet=print("Hello, $1!");
@greet World # → prints Hello, World!
Keyboard shortcuts — Up/Down history, Home/Ctrl-A, End/Ctrl-E,
Ctrl-U, Ctrl-K, Ctrl-L, Ctrl-C (cancel async / exit on second press).
---
Quick Start
Running the REPL interactively
dart run tom_d4rt_dcli:dcli
The banner shows the tool version. Type help for the full command reference.
Evaluating a single expression
dart run tom_d4rt_dcli:dcli "DateTime.now()"
dart run tom_d4rt_dcli:dcli "env['HOME']"
Executing a Dart file
dart run tom_d4rt_dcli:dcli myscript.dart
Running a replay file
dart run tom_d4rt_dcli:dcli my_setup.dcli
Shebang scripts — run .dart files like shell scripts
Once the dcli binary is on your PATH (compiled from a downstream tool, or via
dart pub global activate), a D4rt script can carry a shebang and run directly:
#!/usr/bin/env dcli
import 'package:dcli/dcli.dart';
// A throwaway maintenance script — no compile step needed.
final stale = find('*.tmp', workingDirectory: '.').toList();
for (final f in stale) {
print('removing $f');
delete(f);
}
print('cleaned ${stale.length} temp files');
chmod +x cleanup.dart
./cleanup.dart # the shebang routes the file through dcli
Piping scripts via stdin
For one-liners, generated code, or composing with other shell tools, pipe the source straight into dcli --stdin. The process exit code is the script's return value, so scripts compose into pipelines and
&& chains:
echo 'print(42);' | dcli --stdin
cat my_script.dart | dcli --stdin
echo 'return 5 + 6;' | dcli --stdin # exit code = 11
generate_script | dcli --stdin && echo ok # gate on the script's result
Extending D4rtReplBase to build your own CLI tool
D4rtReplBase is the abstract backbone. Subclass it and override the extension points:
import 'package:tom_d4rt/tom_d4rt.dart';
import 'package:tom_d4rt_dcli/tom_d4rt_dcli.dart';
class MyToolRepl extends D4rtReplBase {
@override
String get toolName => 'MyTool';
@override
String get toolVersion => '1.0.0';
/// Called once at startup — register every bridge the tool needs.
@override
void registerBridges(D4rt d4rt) {
// Register the base dcli bridges provided by this package:
TomD4rtDcliBridge.register(d4rt);
// Add your own bridges here...
}
/// Return the import block prepended to every script.
@override
String getImportBlock() {
return getStdlibImports() + TomD4rtDcliBridge.getImportBlock();
}
/// Describe available bridges in the `help` output.
@override
String getBridgesHelp([D4rt? d4rt]) => 'Bridges: dcli, my_custom_package';
/// Handle tool-specific REPL commands.
/// Return true to consume the command, false to fall through.
@override
Future<bool> handleAdditionalCommands(
D4rt d4rt,
ReplState state,
String line, {
bool silent = false,
}) async {
if (line == 'my-command') {
print('Handled by MyTool!');
return true;
}
return false;
}
}
Future<void> main(List<String> arguments) async {
await MyToolRepl().run(arguments);
}
To also include VS Code integration, mix in VSCodeIntegrationMixin (as DcliRepl
itself does) and call initVSCodeIntegration() inside createReplState, then delegate to
handleVSCodeCommands from handleAdditionalCommands.
Using the cli global variable inside scripts
Every D4rt session exposes a cli global (type D4rtCliApi) that gives scripts programmatic access to REPL operations:
// Inside a D4rt script or replay file
cli.cd('/my/project');
await cli.replay('setup.dcli');
final allClasses = cli.classes();
for (final c in allClasses) {
print('${c.name}: ${c.methods.length} methods');
}
final result = await cli.eval('1 + 2');
print(result); // 3
---
Examples
The example/
folder is the canonical DCli sample home for the D4rt CLI ecosystem. Alongside the single-file snippets it ships two extended, multi-file CLI applications:
| Sample | Description |
|---|---|
example/build_suite/
|
Build/automation tool —
BuildTask
hierarchy +
TaskRunner
across files, shell bridges, and a
buildkit.yaml
BuildKit pipeline
|
example/log_pipeline/
|
File-processing pipeline — parse → filter → aggregate stages over generated
.log
files, with a written report and coloured summary
|
Both run unchanged on the analyzer-free sibling tom_dcli_exec, which points back here instead of duplicating samples.
For a standalone, repo-curated walkthrough see the d4rt_dcli_sample
in the shared tom_d4rt_samples collection — a self-contained DCli scripting tour sitting alongside the interpreter, Flutter, and advanced samples.
---
Architecture
Stacked-REPL design
D4rtReplBase (abstract base — this package)
│
├─ DcliRepl + VSCodeIntegrationMixin (concrete dcli REPL — this package)
│
└─ [downstream tool packages extend D4rtReplBase directly]
e.g. tom_dartscript_bridges (d4rt binary),
tom_build_cli (tom binary)
D4rtReplBase owns the full REPL loop, argument parsing, session management, history, multiline input, bot mode, stdin mode,
--help/--version output, and the cli global registration. Downstream tools add only bridges, additional commands, and branding.
Bridge registration
Bridges are generated by tom_d4rt_generator (dev dependency ^1.9.0) via build_runner. The generation marker is tracked in
lib/d4rt_bridges.g.info. The generated bridge modules registered by TomD4rtDcliBridge.register(d4rt)
are:
| Module | Bridged package |
|---|---|
PackageDcliBridge | dcli |
PackageDcliCoreBridge | dcli_core |
PackageDcliTerminalBridge | dcli_terminal |
PackageTomVscodeScriptingApiBridge |
tom_vscode_scripting_api |
PackageTomChattoolsBridge | tom_chattools |
PackageCryptoBridge | crypto |
PackageTomD4rtDcliBridge |
tom_d4rt_dcli itself (the cli API) |
Total bridged classes across all modules: 70 (as of v1.1.4 build 2026-02-07).
Data directory layout
The REPL stores all persistent state under ~/.tom/dcli/:
~/.tom/dcli/
├── .history # Persistent command history (up to 500 lines)
├── dcli_init_source.dart # Optional custom init script (auto-loaded)
├── <session-id>.session.txt # Recorded session files (auto-managed)
---
Ecosystem fit
| Package | Role | Notes |
|---|---|---|
tom_d4rt | Analyzer-based interpreter runtime | Direct dependency |
tom_d4rt_dcli |
This package — dcli CLI base | Analyzer-based |
tom_dcli_exec |
Analyzer-free dcli CLI base | Lighter weight, no analyzer |
tom_dartscript_bridges |
Full D4rt binary (d4rt) |
Extends D4rtReplBase |
tom_build_cli |
Tom workspace CLI (tom) |
Extends D4rtReplBase |
tom_d4rt_generator | Bridge code generator | Dev dependency |
tom_vscode_scripting_api | VS Code bridge API | Runtime dependency |
tom_chattools | Telegram / chat API | Runtime dependency |
All packages live in the tom_d4rt monorepo at github.com/al-the-bear/tom_d4rt. This package resides at
tom_ai/d4rt/tom_d4rt_dcli.
---
Further documentation
| Document | What it covers |
|---|---|
doc/build.md |
Building and compiling the
dcli
binary; bridge regeneration via
build_runner
.
|
doc/testing.md |
Test layout and how to run the suite with testkit. |
doc/tom_d4rt_dcli_limitations.md
|
Known limitations of the dcli REPL and its bridges. |
Related packages
| Package | Relationship |
|---|---|
tom_d4rt |
The source-based interpreter this package is built on. |
tom_dcli_exec |
Analyzer-free twin — same DcliRepl surface on tom_d4rt_exec. |
tom_d4rt_generator |
Generates the dcli bridges (*.b.dart). |
---
Status
Current version: 1.1.6 — duplicate-export collision fixes for AOT-compiled hosted consumers (see
CHANGELOG); bridges regenerated against
tom_d4rt_generator 1.9.0.
Requires Dart SDK ^3.10.4.
tom_d4rt: ^1.8.20
tom_vscode_scripting_api: ^1.0.1
tom_chattools: ^1.0.2
dcli: ^8.4.2
dcli_core: ^8.2.8
dcli_terminal: ^8.4.2
---
License
BSD 3-Clause. See LICENSE.
License
BSD 3-Clause License Copyright (c) 2024-2026, Peter Nicolai Alexis Kyaw Find me on LinkedIn under Alexis Kyaw All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.