tasktree 0.0.6__py3-none-any.whl → 0.0.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ tasktree/__init__.py,sha256=MVmdvKb3JdqLlo0x2_TPGMfgFC0HsDnP79HAzGnFnjI,1081
2
+ tasktree/cli.py,sha256=bPojvR7kS2iQomNFSykYsrOgD4Nc5XAH4XbEfdVL9qk,15736
3
+ tasktree/docker.py,sha256=R69NcZw4MyaxEXyJAwniYCm877iaI10jRhxlLmkA6Fs,14119
4
+ tasktree/executor.py,sha256=iZ_BF3pjyxhH6l2p78rLSK54Xk-V08Ae_BVF6CIi3jo,38979
5
+ tasktree/graph.py,sha256=lA3ExNM_ag0AlC6iW20unseCjRg5wCZXbmXs2M6TnQw,5578
6
+ tasktree/hasher.py,sha256=S4OKsNjf1ZnhGAvRWr6usuAudiozlQqrvcoAGYzJ_w8,2852
7
+ tasktree/parser.py,sha256=K83HyujCyh9NGJoBeUzozYRFQELNHPzWcJoZdPh79yE,56808
8
+ tasktree/state.py,sha256=Cktl4D8iDZVd55aO2LqVyPrc-BnljkesxxkcMcdcfOY,3541
9
+ tasktree/substitution.py,sha256=Sr8_aBdcWXtkCybkSFMHRjQyQSq-cMREtps_A9ASUgk,6320
10
+ tasktree/tasks.py,sha256=2QdQZtJAX2rSGbyXKG1z9VF_siz1DUzdvzCgPkykxtU,173
11
+ tasktree/types.py,sha256=R_YAyO5bMLB6XZnkMRT7VAtlkA_Xx6xu0aIpzQjrBXs,4357
12
+ tasktree-0.0.8.dist-info/METADATA,sha256=JKjK-6i9ZlTq4gCVWl1dJE6W615tjtlQt64bPwi4vcU,34533
13
+ tasktree-0.0.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ tasktree-0.0.8.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
15
+ tasktree-0.0.8.dist-info/RECORD,,
@@ -1,699 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: tasktree
3
- Version: 0.0.6
4
- Summary: A task automation tool with incremental execution
5
- Requires-Python: >=3.11
6
- Requires-Dist: click>=8.1.0
7
- Requires-Dist: colorama>=0.4.6
8
- Requires-Dist: pyyaml>=6.0
9
- Requires-Dist: rich>=13.0.0
10
- Requires-Dist: typer>=0.9.0
11
- Provides-Extra: dev
12
- Requires-Dist: pytest>=9.0.2; extra == 'dev'
13
- Description-Content-Type: text/markdown
14
-
15
- # Task Tree (tt)
16
-
17
- [![Tests](https://github.com/kevinchannon/task-tree/actions/workflows/test.yml/badge.svg)](https://github.com/kevinchannon/task-tree/actions/workflows/test.yml)
18
-
19
- A task automation tool that combines simple command execution with dependency tracking and incremental execution.
20
-
21
- ## Motivation
22
- In any project of even moderate size, various scripts inevitably come into being along the way. These scripts often must be run in a particular order, or at a particular time. For historical reasons, this almost certainly a problem if your project is developed in a Linux environment; in Windows, an IDE like Visual Studio may be taking care of a significant proportion of your build, packaging and deployment tasks. Then again, it may not...
23
-
24
- The various incantations that have to be issued to build, package, test and deploy a project can build up and then all of a sudden there's only a few people that remember which to invoke and when and then people start making helpful readme guides on what to do with the scripts and then those become out of date and start telling lies about things and so on.
25
-
26
- Then there's the scripts themselves. In Linux, they're probably a big pile of Bash and Python, or something (Ruby, Perl, you name it). You can bet the house on people solving the problem of passing parameters to their scripts in a whole bunch of different and inconsistent ways.
27
-
28
- ```bash
29
- #!/usr/bin/env bash
30
- # It's an environment variable defined.... somewhere?
31
- echo "FOO is: $FOO"
32
- ```
33
- ```bash
34
- #!/usr/bin/env bash
35
- # Using simple positional arguments... guess what means what when you're invoking it!
36
- echo "First: $1, Second: $2"
37
- ```
38
- ```bash
39
- #!/usr/bin/env bash
40
- # Oooooh fancy "make me look like a proper app" named option parsing... don't try and do --foo=bar though!
41
- FOO=""
42
- while [[ $# -gt 0 ]]; do
43
- case "$1" in
44
- --foo) FOO=$2; shift ;;
45
- --) break ;;
46
- *) echo "Unknown: $1";;
47
- esac
48
- shift
49
- done
50
- ```
51
- ```bash
52
- #!/usr/bin/env bash
53
- # This thing...
54
- ARGS=$(getopt -o f:b --long foo:,bar: -n 'myscript' -- "$@")
55
- eval set -- "$ARGS"
56
- while true; do
57
- case "$1" in
58
- -b|--bar) echo "Bar: $2"; shift 2 ;;
59
- -f|--foo) echo "Foo: $2"; shift 2 ;;
60
- --) shift; break ;;
61
- *) break ;;
62
- esac
63
- done
64
- ```
65
-
66
- What about help info? Who has time to wire that in?
67
-
68
- ### The point
69
- Is this just whining and moaning? Should we just man up and revel in our own ability to memorize all the right incantations like some kind of scripting shaman?
70
-
71
- ... No. That's **a dumb idea**.
72
-
73
- Task Tree allows you to pile all the knowledge of **what** to run, **when** to run it, **where** to run it and **how** to run it into a single, readable place. Then you can delete all the scripts that no-one knows how to use and all the readme docs that lie to the few people that actually waste their time reading them.
74
-
75
- The tasks you need to perform to deliver your project become summarised in an executable file that looks like:
76
- ```yaml
77
- tasks:
78
- build:
79
- desc: Compile stuff
80
- outputs: [target/release/bin]
81
- cmd: cargo build --release
82
-
83
- package:
84
- desc: build installers
85
- deps: [build]
86
- outputs: [awesome.deb]
87
- cmd: |
88
- for bin in target/release/*; do
89
- if [[ -x "$bin" && ! -d "$bin" ]]; then
90
- install -Dm755 "$bin" "debian/awesome/usr/bin/$(basename "$bin")"
91
- fi
92
- done
93
-
94
- dpkg-buildpackage -us -uc
95
-
96
- test:
97
- desc: Run tests
98
- deps: [package]
99
- inputs: [tests/**/*.py]
100
- cmd: PYTHONPATH=src python3 -m pytest tests/ -v
101
- ```
102
-
103
- If you want to run the tests then:
104
- ```bash
105
- tt test
106
- ```
107
- Boom! Done. `build` will always run, because there's no sensible way to know what Cargo did. However, if Cargo decided that nothing needed to be done and didn't touch the binaries, then `package` will realize that and not do anything. Then `test` will just run with the new tests that you just wrote. If you then immediately run `test` again, then `test` will figure out that none of the dependencies did anything and that none of the test files have changed and then just _do nothing_ - as it should.
108
-
109
- This is a toy example, but you can image how it plays out on a more complex project.
110
-
111
- ## Migrating from v1.x to v2.0
112
-
113
- Version 2.0 requires all task definitions to be under a top-level `tasks:` key.
114
-
115
- ### Quick Migration
116
-
117
- Wrap your existing tasks in a `tasks:` block:
118
-
119
- ```yaml
120
- # Before (v1.x)
121
- build:
122
- cmd: cargo build
123
-
124
- # After (v2.0)
125
- tasks:
126
- build:
127
- cmd: cargo build
128
- ```
129
-
130
- ### Why This Change?
131
-
132
- 1. **Clearer structure**: Explicit separation of tasks from configuration
133
- 2. **No naming conflicts**: You can now create tasks named "imports" or "environments"
134
- 3. **Better error messages**: More helpful validation errors
135
- 4. **Consistency**: All recipe files use the same format
136
-
137
- ### Error Messages
138
-
139
- If you forget to update, you'll see a clear error:
140
-
141
- ```
142
- Invalid recipe format in tasktree.yaml
143
-
144
- Task definitions must be under a top-level "tasks:" key.
145
-
146
- Found these keys at root level: build, test
147
-
148
- Did you mean:
149
-
150
- tasks:
151
- build:
152
- cmd: ...
153
- test:
154
- cmd: ...
155
- ```
156
-
157
- ## Installation
158
-
159
- ### From PyPI (Recommended)
160
-
161
- ```bash
162
- pipx install tasktree
163
- ```
164
-
165
- If you have multiple Python interpreter versions installed, and the _default_ interpreter is a version <3.11, then you can use `pipx`'s `--python` option to specify an interpreter with a version >=3.11:
166
-
167
- ```bash
168
- # If the target version is on the PATH
169
- pipx install --python python3.12 tasktree
170
-
171
- # With a path to an interpreter
172
- pipx install --python /path/to/python3.12 tasktree
173
- ```
174
-
175
- ### From Source
176
-
177
- For the latest unreleased version from GitHub:
178
-
179
- ```bash
180
- pipx install git+https://github.com/kevinchannon/task-tree.git
181
- ```
182
-
183
- Or to install from a local clone:
184
-
185
- ```bash
186
- git clone https://github.com/kevinchannon/task-tree.git
187
- cd tasktree
188
- pipx install .
189
- ```
190
-
191
- ## Editor Support
192
-
193
- Task Tree includes a [JSON Schema](schema/tasktree-schema.json) that provides autocomplete, validation, and documentation in modern editors.
194
-
195
- ### VS Code
196
-
197
- Install the [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml), then add to your workspace `.vscode/settings.json`:
198
-
199
- ```json
200
- {
201
- "yaml.schemas": {
202
- "https://raw.githubusercontent.com/kevinchannon/tasktree/main/schema/tasktree-schema.json": [
203
- "tasktree.yaml",
204
- "tt.yaml"
205
- ]
206
- }
207
- }
208
- ```
209
-
210
- Or add a comment at the top of your `tasktree.yaml`:
211
-
212
- ```yaml
213
- # yaml-language-server: $schema=https://raw.githubusercontent.com/kevinchannon/tasktree/main/schema/tasktree-schema.json
214
-
215
- tasks:
216
- build:
217
- cmd: cargo build
218
- ```
219
-
220
- See [schema/README.md](schema/README.md) for IntelliJ/PyCharm and command-line validation.
221
-
222
- ## Quick Start
223
-
224
- Create a `tasktree.yaml` (or `tt.yaml`) in your project:
225
-
226
- ```yaml
227
- tasks:
228
- build:
229
- desc: Compile the application
230
- outputs: [target/release/bin]
231
- cmd: cargo build --release
232
-
233
- test:
234
- desc: Run tests
235
- deps: [build]
236
- cmd: cargo test
237
- ```
238
-
239
- Run tasks:
240
-
241
- ```bash
242
- tt # Print the help
243
- tt --help # ...also print the help
244
- tt --list # Show all available tasks
245
- tt build # Build the application (assuming this is in your tasktree.yaml)
246
- tt test # Run tests (builds first if needed)
247
- ```
248
-
249
- ## Core Concepts
250
-
251
- ### Intelligent Incremental Execution
252
-
253
- Task Tree only runs tasks when necessary. A task executes if:
254
-
255
- - Its definition (command, outputs, working directory, environment) has changed
256
- - Any input files have changed since the last run
257
- - Any dependencies have re-run
258
- - It has never been executed before
259
- - It has no inputs or outputs (always runs)
260
- - The execution environment has changed (CLI override or environment config change)
261
-
262
- ### Automatic Input Inheritance
263
-
264
- Tasks automatically inherit inputs from dependencies, eliminating redundant declarations:
265
-
266
- ```yaml
267
- tasks:
268
- build:
269
- outputs: [dist/app]
270
- cmd: go build -o dist/app
271
-
272
- package:
273
- deps: [build]
274
- outputs: [dist/app.tar.gz]
275
- cmd: tar czf dist/app.tar.gz dist/app
276
- # Automatically tracks dist/app as an input
277
- ```
278
-
279
- ### Single State File
280
-
281
- All state lives in `.tasktree-state` at your project root. Stale entries are automatically pruned—no manual cleanup needed.
282
-
283
- ## Task Definition
284
-
285
- ### Basic Structure
286
-
287
- ```yaml
288
- tasks:
289
- task-name:
290
- desc: Human-readable description (optional)
291
- deps: [other-task] # Task dependencies
292
- inputs: [src/**/*.go] # Explicit input files (glob patterns)
293
- outputs: [dist/binary] # Output files (glob patterns)
294
- working_dir: subproject/ # Execution directory (default: project root)
295
- env: bash-strict # Execution environment (optional)
296
- args: [param1, param2:path=default] # Task parameters
297
- cmd: go build -o dist/binary # Command to execute
298
- ```
299
-
300
- ### Commands
301
-
302
- **Single-line commands** are executed directly via the configured shell:
303
-
304
- ```yaml
305
- tasks:
306
- build:
307
- cmd: cargo build --release
308
- ```
309
-
310
- **Multi-line commands** are written to temporary script files for proper execution:
311
-
312
- ```yaml
313
- tasks:
314
- deploy:
315
- cmd: |
316
- mkdir -p dist
317
- cp build/* dist/
318
- rsync -av dist/ server:/opt/app/
319
- ```
320
-
321
- Multi-line commands preserve shell syntax (line continuations, heredocs, etc.) and support shebangs on Unix/macOS.
322
-
323
- Or use folded blocks for long single-line commands:
324
-
325
- ```yaml
326
- tasks:
327
- compile:
328
- cmd: >
329
- gcc -o bin/app
330
- src/*.c
331
- -I include
332
- -L lib -lm
333
- ```
334
-
335
- ### Execution Environments
336
-
337
- Configure custom shell environments for task execution:
338
-
339
- ```yaml
340
- environments:
341
- default: bash-strict
342
-
343
- bash-strict:
344
- shell: bash
345
- args: ['-c'] # For single-line: bash -c "command"
346
- preamble: | # For multi-line: prepended to script
347
- set -euo pipefail
348
-
349
- python:
350
- shell: python
351
- args: ['-c']
352
-
353
- powershell:
354
- shell: powershell
355
- args: ['-ExecutionPolicy', 'Bypass', '-Command']
356
- preamble: |
357
- $ErrorActionPreference = 'Stop'
358
-
359
- tasks:
360
- build:
361
- # Uses 'default' environment (bash-strict)
362
- cmd: cargo build --release
363
-
364
- analyze:
365
- env: python
366
- cmd: |
367
- import sys
368
- print(f"Analyzing with Python {sys.version}")
369
- # ... analysis code ...
370
-
371
- windows-task:
372
- env: powershell
373
- cmd: |
374
- Compress-Archive -Path dist/* -DestinationPath package.zip
375
- ```
376
-
377
- **Environment resolution priority:**
378
- 1. CLI override: `tt --env python build`
379
- 2. Task's `env` field
380
- 3. Recipe's `default` environment
381
- 4. Platform default (bash on Unix, cmd on Windows)
382
-
383
- **Platform defaults** when no environments are configured:
384
- - **Unix/macOS**: bash with `-c` args
385
- - **Windows**: cmd with `/c` args
386
-
387
- ### Parameterised Tasks
388
-
389
- Tasks can accept arguments with optional defaults:
390
-
391
- ```yaml
392
- tasks:
393
- deploy:
394
- args: [environment, region=eu-west-1]
395
- deps: [build]
396
- cmd: |
397
- aws s3 cp dist/app.zip s3://{{environment}}-{{region}}/
398
- aws lambda update-function-code --function-name app-{{environment}}
399
- ```
400
-
401
- Invoke with: `tt deploy production` or `tt deploy staging us-east-1` or `tt deploy staging region=us-east-1`.
402
-
403
- Arguments may be typed, or not and have a default, or not. Valid argument types are:
404
-
405
- * int - an integer value (e.g. 0, 10, 123, -9)
406
- * float - a floating point value (e.g. 1.234, -3.1415, 2e-4)
407
- * bool - Boolean-ish value (e.g. true, false, yes, no, 1, 0, etc)
408
- * str - a string
409
- * path - a pathlike string
410
- * datetime - a datetime in the format 2025-12-17T16:56:12
411
- * ip - an ip address (v4 or v6)
412
- * ipv4 - an IPv4 value
413
- * ipv6 - an IPv6 value
414
- * email - String validated, but not positively confirmed to be a reachable address.
415
- * hostname - looks like a hostname, resolution of the name is not attempted as part of the validation
416
-
417
- Different argument values are tracked separately—tasks re-run when invoked with new arguments.
418
-
419
- ## File Imports
420
-
421
- Split task definitions across multiple files for better organisation:
422
-
423
- ```yaml
424
- # tasktree.yaml
425
- imports:
426
- - file: build/tasks.yml
427
- as: build
428
- - file: deploy/tasks.yml
429
- as: deploy
430
-
431
- tasks:
432
- test:
433
- deps: [build.compile, build.test-compile]
434
- cmd: ./run-tests.sh
435
-
436
- ci:
437
- deps: [build.all, test, deploy.staging]
438
- ```
439
-
440
- Imported tasks are namespaced and can be referenced as dependencies. Each imported file is self-contained—it cannot depend on tasks in the importing file.
441
-
442
- ## Glob Patterns
443
-
444
- Input and output patterns support standard glob syntax:
445
-
446
- - `src/*.rs` — All Rust files in `src/`
447
- - `src/**/*.rs` — All Rust files recursively
448
- - `{file1,file2}` — Specific files
449
- - `**/*.{js,ts}` — Multiple extensions recursively
450
-
451
- ## State Management
452
-
453
- ### How State Works
454
-
455
- Each task is identified by a hash of its definition. The hash includes:
456
-
457
- - Command to execute
458
- - Output patterns
459
- - Working directory
460
- - Argument definitions
461
- - Execution environment
462
-
463
- State tracks:
464
- - When the task last ran
465
- - Timestamps of input files at that time
466
-
467
- Tasks are re-run when their definition changes, inputs are newer than the last run, or the environment changes.
468
-
469
- ### What's Not In The Hash
470
-
471
- Changes to these don't invalidate cached state:
472
-
473
- - Task name (tasks can be renamed freely)
474
- - Description
475
- - Dependencies (only affects execution order)
476
- - Explicit inputs (tracked by timestamp, not definition)
477
-
478
- ### Automatic Cleanup
479
-
480
- At the start of each invocation, state is checked for invalid task hashes and non-existent ones are automatically removed. Delete a task from your recipe file and its state disappears the next time you run `tt <cmd>`
481
-
482
- ## Command-Line Options
483
-
484
- Task Tree provides several command-line options for controlling task execution:
485
-
486
- ### Execution Control
487
-
488
- ```bash
489
- # Force re-run (ignore freshness checks)
490
- tt --force build
491
- tt -f build
492
-
493
- # Run only the specified task, skip dependencies (implies --force)
494
- tt --only deploy
495
- tt -o deploy
496
-
497
- # Override environment for all tasks
498
- tt --env python analyze
499
- tt -e powershell build
500
- ```
501
-
502
- ### Information Commands
503
-
504
- ```bash
505
- # List all available tasks
506
- tt --list
507
- tt -l
508
-
509
- # Show detailed task definition
510
- tt --show build
511
-
512
- # Show dependency tree (without execution)
513
- tt --tree deploy
514
-
515
- # Show version
516
- tt --version
517
- tt -v
518
-
519
- # Create a blank recipe file
520
- tt --init
521
- ```
522
-
523
- ### State Management
524
-
525
- ```bash
526
- # Remove state file (reset task cache)
527
- tt --clean
528
- tt --clean-state
529
- tt --reset
530
- ```
531
-
532
- ### Common Workflows
533
-
534
- ```bash
535
- # Fresh build of everything
536
- tt --force build
537
-
538
- # Run a task without rebuilding dependencies
539
- tt --only test
540
-
541
- # Test with a different shell/environment
542
- tt --env python test
543
-
544
- # Force rebuild and deploy
545
- tt --force deploy production
546
- ```
547
-
548
- ## Example: Full Build Pipeline
549
-
550
- ```yaml
551
- imports:
552
- - file: common/docker.yml
553
- as: docker
554
-
555
- tasks:
556
- compile:
557
- desc: Build application binaries
558
- outputs: [target/release/app]
559
- cmd: cargo build --release
560
-
561
- test-unit:
562
- desc: Run unit tests
563
- deps: [compile]
564
- cmd: cargo test
565
-
566
- package:
567
- desc: Create distribution archive
568
- deps: [compile]
569
- outputs: [dist/app-{{version}}.tar.gz]
570
- args: [version]
571
- cmd: |
572
- mkdir -p dist
573
- tar czf dist/app-{{version}}.tar.gz \
574
- target/release/app \
575
- config/ \
576
- migrations/
577
-
578
- deploy:
579
- desc: Deploy to environment
580
- deps: [package, docker.build-runtime]
581
- args: [environment, version]
582
- cmd: |
583
- scp dist/app-{{version}}.tar.gz {{environment}}:/opt/
584
- ssh {{environment}} /opt/deploy.sh {{version}}
585
-
586
- integration-test:
587
- desc: Run integration tests against deployed environment
588
- deps: [deploy]
589
- args: [environment, version]
590
- cmd: pytest tests/integration/ --env={{environment}}
591
- ```
592
-
593
- Run the full pipeline:
594
-
595
- ```bash
596
- tt integration-test staging version=1.2.3
597
- ```
598
-
599
- This will:
600
- 1. Compile if sources have changed
601
- 2. Run unit tests if compilation ran
602
- 3. Package if compilation ran or version argument is new
603
- 4. Build Docker runtime (from imported file) if needed
604
- 5. Deploy if package or Docker image changed
605
- 6. Run integration tests (always runs)
606
-
607
- ## Implementation Notes
608
-
609
- Built with Python 3.11+ using:
610
-
611
- - **PyYAML** for recipe parsing
612
- - **Typer**, **Click**, **Rich** for CLI
613
- - **graphlib.TopologicalSorter** for dependency resolution
614
- - **pathlib** for file operations and glob expansion
615
-
616
- State file uses JSON format for simplicity and standard library compatibility.
617
-
618
- ## Development
619
-
620
- ### Setup Development Environment
621
-
622
- ```bash
623
- # Clone repository
624
- git clone https://github.com/kevinchannon/task-tree.git
625
- cd tasktree
626
-
627
- # Install uv (if not already installed)
628
- curl -LsSf https://astral.sh/uv/install.sh | sh
629
-
630
- # Install dependencies
631
- uv sync
632
-
633
- # Install in editable mode
634
- pipx install -e .
635
- ```
636
-
637
- ### Running Tests
638
-
639
- ```bash
640
- # Run all tests
641
- uv run pytest
642
-
643
- # Run with verbose output
644
- uv run pytest -v
645
-
646
- # Run specific test file
647
- uv run pytest tests/unit/test_executor.py
648
- ```
649
-
650
- ### Using Task Tree for Development
651
-
652
- The repository includes a `tasktree.yaml` with development tasks:
653
-
654
- ```bash
655
- tt test # Run tests
656
- tt build # Build wheel package
657
- tt install-dev # Install package in development mode
658
- tt clean # Remove build artifacts
659
- ```
660
-
661
- ## Releasing
662
-
663
- New releases are created by pushing version tags to GitHub. The release workflow automatically:
664
- - Builds wheel and source distributions
665
- - Creates a GitHub Release with artifacts
666
- - Publishes to PyPI via trusted publishing
667
-
668
- ### Release Process
669
-
670
- 1. Ensure main branch is ready:
671
- ```bash
672
- git checkout main
673
- git pull
674
- ```
675
-
676
- 2. Create and push a version tag:
677
- ```bash
678
- git tag v1.0.0
679
- git push origin v1.0.0
680
- ```
681
-
682
- 3. GitHub Actions will automatically:
683
- - Extract version from tag (e.g., `v1.0.0` → `1.0.0`)
684
- - Update `pyproject.toml` with the version
685
- - Build wheel and sdist
686
- - Create GitHub Release
687
- - Publish to PyPI
688
-
689
- 4. Verify the release:
690
- - GitHub: https://github.com/kevinchannon/task-tree/releases
691
- - PyPI: https://pypi.org/kevinchannon/tasktree/
692
- - Test: `pipx install --force tasktree`
693
-
694
- ### Version Numbering
695
-
696
- Follow semantic versioning:
697
- - `v1.0.0` - Major release (breaking changes)
698
- - `v1.1.0` - Minor release (new features, backward compatible)
699
- - `v1.1.1` - Patch release (bug fixes)