Build a feature with Claude Code

In Tutorial 3 you built a feature by hand. Here you’ll build the same kind of feature, a list of bookmarks owned by the user, by describing it. The Claude Code plugin does the scaffolding, writes the code and tests, wires it into the SPL and product, migrates, and verifies.

Table of contents

Prerequisites

  • The Claude Code plugin installed. See Claude Code → Installation.
  • A product to build into (e.g. my_first_app from Tutorial 1) with the SPLENT CLI container running.
  • A feature name that is still free. my_first_app already has splent_feature_notes from Tutorial 3, which is why this tutorial builds bookmarks instead of notes.

Step 1. Describe what you want

You don’t type CLI commands. In Claude Code, just say what the feature is.

add a bookmarks feature with a title and a URL, owned by the user

Claude recognises this as SPLENT feature work and runs the feature skill. It infers a name (splent_feature_bookmarks), an archetype (full, because it has a model), and that “owned by the user” means a foreign key to the auth user table, so it depends on auth. It states that plan in a couple of lines before it starts.

Step 2. What Claude does

The skill drives the CLI end-to-end, writing real code at each step.

# scaffold the package (feature creation is workspace-level)
splent product:deselect
splent feature:create splent-io/splent_feature_bookmarks --type full

# write idiomatic code (Claude does this, following the conventions):
#   models.py        Bookmarks(id, title, url, user_id → user.id, created_at)
#   repositories.py  custom queries on BaseRepository
#   services.py      business logic on BaseService
#   routes.py        @login_required /bookmarks/ (resolved via service_proxy)
#   forms.py, templates/bookmarks/index.html, hooks.py (sidebar), seeders.py
#   tests/unit, tests/integration, tests/functional

# add to the SPL (spl:* runs detached; dependencies are auto-detected)
splent spl:add-feature sample_splent_spl splent_feature_bookmarks   # → bookmarks => auth

# install into the product
splent product:select my_first_app
splent feature:add splent-io/splent_feature_bookmarks

# infer and write the contract (needs a selected product)
splent feature:contract splent_feature_bookmarks --write

# migrate
splent db:migrate splent_feature_bookmarks
splent db:upgrade

These are the same commands you typed in Tutorial 3, in the same order.

Claude follows two rules throughout. The CLI owns the mechanics (it never hand-edits pyproject feature lists, the .uvl model, or migration tables), and you own the logic (models, services, routes, templates, tests).

Step 3. Verify

splent feature:test splent_feature_bookmarks   # unit, integration, functional
splent feature:xray --validate                 # hooks/extension wiring OK
splent product:validate                        # UVL satisfiable, contracts compatible, imports OK
splent product:routes | grep bookmarks

product:routes prints one line per route and method, in the same shape as the notes routes you built by hand.

  /notes/                              GET     splent_feature_notes       notes.index
  /notes/<int:note_id>/delete          POST    splent_feature_notes       notes.delete
  /notes/<subfolder>/<filename>        GET     splent_feature_notes       notes.assets
  /notes/create                        GET     splent_feature_notes       notes.create
  /notes/create                        POST    splent_feature_notes       notes.create

The assets route is not one you wrote: a feature with an assets/ folder, which the scaffold creates, serves its JavaScript and CSS from it under its prefix.

Open http://localhost:5591/login, log in, and go to the new page (/bookmarks/, or whatever route Claude reported). Its sidebar has a Bookmarks link next to Notes, and the page lists the current user’s bookmarks and lets them add and delete their own. Claude writes the code afresh each time, so names and details can differ from this description; the summary it prints at the end says what it built.

When the app won’t boot

If product:derive fails with ValueError: Unrecognized value for SESSION_TYPE: null, the product has no session backend selected. Ask Claude for help.

/splent:doctor the app won't start, SESSION_TYPE is null

The doctor skill diagnoses it and adds a session feature (splent_feature_session_filesystem or _redis) to the SPL and product, then re-derives.

What you end up with

A complete, tested feature, splent_feature_bookmarks, added to the SPL with a bookmarks => auth constraint, installed and migrated into your product, and serving a login-protected page. The same kind of result as Tutorial 3, reached by describing the feature instead of writing every file.

Tips

  • Prefer describing intent; the right skill (feature, product, doctor) triggers automatically. See the Skills reference.
  • Review the diff like any change. Claude writes idiomatic SPLENT code, but it’s your feature.

Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es