Exploring your product
Use SPLENT’s inspection tools to understand how features are composed, ordered, and validated.
Table of contents
- Prerequisites
- Feature status
- Feature load order
- Dependency impact
- Composition map (xray)
- Infrastructure check
- SPL validation
- SPL queries
- Full diagnostic
- Where things live
- What you learned
- Next
Prerequisites
You completed Tutorial 1 and have my_first_app running with auth, public, redis, session_redis, and profile.
Feature status
splent feature:status
This shows every feature and its current lifecycle state:
Feature Mode Progress State
──────────────────────────────────────────────────────────────────────────────
splent_io/splent_feature_auth@v1.5.5 pinned ●─●─●─● active
splent_io/splent_feature_profile@v1.5.4 pinned ●─●─●─● active
splent_io/splent_feature_public@v1.5.3 pinned ●─●─○─● active
splent_io/splent_feature_redis@v1.5.4 pinned ●─●─○─● active
splent_io/splent_feature_session_redis@v1.0.5 pinned ●─●─○─● active
States progress through the lifecycle: declared (in pyproject.toml) → installed (pip-installed) → migrated (database tables created) → active (registered in Flask). All five features are active because product:derive ran the full pipeline.
Notice that public, redis, and session_redis show ○ for the migrated step — they have no database tables, so that step is skipped. The progress bar reflects this accurately.
Feature load order
splent feature:order --short
Feature load order — my_first_app
──────────────────────────────────────────────
# Feature Requires
──────────────────────────────────────────────
1 splent_feature_auth —
2 splent_feature_profile splent_feature_auth
3 splent_feature_redis —
4 splent_feature_session_redis splent_feature_redis
5 splent_feature_public —
UVL: sample_splent_spl.uvl
Load order matters because features depend on each other’s models and hooks. The order comes from UVL constraints: profile => auth means profile always loads after auth, and session_redis => redis means the session backend loads after Redis is available. This guarantees that dependencies are satisfied before the features that need them.
Dependency impact
Once you know the load order, the natural next question is: what happens if I add or remove a feature?
splent feature:impact auth
feature:impact — auth
Product: my_first_app
UVL: sample_splent_spl.uvl
Depends on
(none) — this feature is independent
Depended on by
← confirmemail (direct)
← notes (direct)
← notes_tags (transitive)
← profile (direct)
← reset (direct)
Removing auth would break 5 feature(s).
The command reads the UVL constraints and builds a bidirectional dependency graph. Depends on shows what the feature needs to work; Depended on by shows what would break if you removed it. Dependencies are labelled as direct (declared in the UVL) or transitive (propagated through the graph).
Try it with a leaf feature:
splent feature:impact profile
feature:impact — profile
Product: my_first_app
UVL: sample_splent_spl.uvl
Depends on
→ auth (direct)
Depended on by
(none) — safe to remove
Removing profile has no impact on other features.
Profile depends on auth but nothing depends on profile — it can be safely removed. This is useful before running feature:remove or when planning which features to include in a new product.
Composition map (xray)
splent feature:xray
This prints the full composition of your product:
- Product layout — which hooks are active in
base_template.htmland which features fill them - Extension points — what each feature declares as overridable (services, templates, models, hooks)
- Refinements — what’s been overridden by refinement features (none yet)
To validate the composition is clean:
splent feature:xray --validate
✅ Services: no collisions (2 unique)
✅ Models: no collisions (2 unique)
✅ Routes: no collisions (5 unique)
✅ Blueprints: no collisions (5 unique)
✅ Commands: no collisions (0 unique)
✅ Signals: no collisions (1 unique)
ℹ️ Hook 'layout.navbar.authenticated' — 2 contributors: splent_feature_auth, splent_feature_profile
ℹ️ Hook 'layout.scripts' — 3 contributors: splent_feature_auth, splent_feature_profile, splent_feature_public
✅ Hooks: 2 shared slot(s) — additive, OK
ℹ️ Layout: 3 unused hook(s): layout.head.css, layout.sidebar.top, layout.footer
✅ Layout: 6/9 hooks active
✅ All 8 checks passed.
If everything is green, your product is correctly composed. Shared hooks (like layout.navbar.authenticated used by both auth and profile) are OK — they’re additive by design.
Infrastructure check
splent check:infra
This validates Docker infrastructure without starting any containers: port conflicts between features, duplicate container names, and missing external networks. Useful when adding new features with Docker services.
SPL validation
splent product:validate
Checks your product’s feature selection against the SPL constraints:
- All mandatory features present
- All dependency constraints satisfied (
profile => auth) - No conflicting features selected
SPL queries
These commands operate on the SPL itself (the feature model), not your product. They require detached mode:
splent product:deselect
List all features defined in the SPL:
splent spl:features sample_splent_spl
- auth
- confirmemail
- mail
- mailhog
- notes
- profile
- public
- redis
- reset
- sample_splent_app (root)
- session_filesystem
- session_redis
- session_type
The (root) entry is the SPL itself — it’s the top-level feature in the UVL hierarchy, not a real feature you install.
Check why a feature has dependencies:
splent spl:deps profile sample_splent_spl
Dependencies of 'profile' (features it requires):
- auth
See who depends on a feature (reverse lookup):
splent spl:deps auth sample_splent_spl --reverse
Reverse dependencies of 'auth' (features that require it):
- confirmemail
- profile
- reset
When you’re done, re-select the product:
splent product:select my_first_app
Full diagnostic
splent doctor --fast
Runs 14 checks in sequence: version, environment, pyproject, features, dependencies, product, feature status, outdated, Docker, infrastructure, containers, database, GitHub, and PyPI. Some checks are skipped with --fast. Use it whenever something feels off.
Where things live
| File | Purpose |
|---|---|
my_first_app/pyproject.toml |
Feature declarations, SPL reference, layout hooks |
splent_catalog/sample_splent_spl/ |
SPL metadata (UVL model downloaded on demand via spl:fetch) |
my_first_app/splent.manifest.json |
Lifecycle state of every feature |
.splent_cache/features/ |
Read-only clones of pinned feature versions |
my_first_app/features/splent_io/ |
Symlinks to cached or editable features |
my_first_app/docker/ |
Docker Compose files, Dockerfiles, .env files |
What you learned
| Tool | Purpose |
|---|---|
feature:status |
Lifecycle state of every feature |
feature:order |
UVL-resolved load order |
feature:impact |
Dependency impact analysis (what breaks if removed) |
feature:xray |
Full composition map |
feature:xray --validate |
Validate extensibility (collisions, hooks, refinements) |
check:infra |
Docker port/container/network validation |
product:validate |
Check configuration against SPL constraints |
spl:features / spl:deps |
Query the SPL catalog |
doctor |
Comprehensive health check |
Next
Tutorial 3: Create a feature — build a note-taking feature from scratch.