dev
dev
A Crystal shard providing a single dev CLI tool plus the shared Dev support library (Dev::CLI, Dev::Theme, Dev::Graph, Dev::Terminal, Dev::Git, Dev::Diff, Dev::LLM, Dev::Proposal) it is built on.
Tool
dev is one command with flat subcommands: a two-branch git workflow (init/clone/open/save/undo/release/status/backup/remote), three DeepSeek-backed history commands (find/explain/notes), and three analysis subcommands (tok/loc/chlog).
Git workflow
The model: all work happens on dev; main is a publish target of clean squash-merged releases and is never worked on directly. Feature branches do not exist. Branches are never deleted, nothing is force-pushed (except one guarded amend of main's tip), and mutating operations refuse to run on a dirty tree — except undo --hard, which discards the uncommitted changes. The GitHub repo itself is only deleted by an explicit remote --del, after a backup bundle.
dev init initialize a git repository here (on main) and create its remote;
refuses when backup bundles or the GitHub repo already exist
dev clone <owner/name | url> [<dir>] clone a GitHub repo, then land on dev (runs dev open)
dev open sync main, checkout or create dev, fast-forward and push
(creates the remote if missing)
dev save [-m MSG] [--no-add] [--no-push] commit all changes on dev and push (-m optional in a
terminal with $DEEPSEEK_API_KEY: message proposed)
dev undo [--hard] revert the last commit or merge on dev and push;
--hard discards uncommitted changes first
dev undo --to REV [--hard] restore dev's content to REV (hash, tag, HEAD~N, ...)
as one new commit and push; later commits stay in history
dev release [-m MSG] [options] bundle backup, squash-merge dev into main, tag the shard.yml
version, reconcile and push (creates the remote if missing)
dev release --no-tag release without tagging or the version guard
dev release --cancel back out of a conflicted release, return to dev
dev release --edit-title -m MSG amend main's tip title (backup, tags moved, force-with-lease)
dev status [-n LIMIT] show branch, dirty files, shard version, unpushed counts,
last backup, and the commit graph
dev backup write a backup bundle of all refs
dev backup --list list backup bundles
dev backup --restore [NAME] restore a bundle's branches and tags as restore/<stamp>/<name>
dev remote show origin's GitHub slug, URL and visibility
dev remote --vis public|private change the visibility of origin's GitHub repo
dev remote --del backup bundle, then delete origin's GitHub repo
Restoring to a commit
dev undo --to REV makes dev's files match REV exactly (files added after it are removed) and commits that as restore to <sha> (<subject>), then pushes. Nothing is rewritten: the commits after REV stay in history, and the next dev release publishes the restored state to main like any other change.
- Refuses when
REVis not a commit, or whendevalready matches it. - Without
--hard, refuses on uncommitted changes; with--hard, discards them first — only afterREVhas been validated. - Any commit git can resolve is accepted; a note is printed when
REVis not indev's history (e.g. arestore/…branch from a backup bundle).
DeepSeek proposals
When DEEPSEEK_API_KEY is set, -m is omitted, and dev runs in a real terminal (stdin and stdout are both TTYs), dev save asks DeepSeek to propose the commit message and, where allowed, a shard.yml version bump. Nothing is committed or edited until you accept. dev release never uses DeepSeek.
proposal (deepseek-flash, 3.1k in / 42 out):
message: add a dry-run flag to release
version: 0.11.0 → 0.12.0 (minor)
reason: new user-facing option; breaking changes are minor while major is 0
docs may need updating:
- README.md: the release synopsis does not list --dry-run
accept? [y]es / [e]dit / [n]o:
- The staged diff (
git diff --cached) is sent. Lockfiles and minified assets are excluded, and patches beyond 48,000 characters are truncated. - Style: the last 20 non-merge commit subjects (skipping generated ones such as
restore to …,Revert "…",bump version to …) are sent as examples, so proposals follow your own wording. - Docs check: when the staged paths include
src/but none ofREADME.md,AGENTS.md,SKILL.md, the existing ones among those files are sent too, and statements the change makes stale are listed under "docs may need updating". It is advisory; nothing is edited. - The header shows the model and the request's token usage.
- A bump is offered only when
v<version>is already tagged (locally or onorigin), i.e. the released version must change before the next release. - The bump is computed locally with
SemanticVersion(patch/minor/major); the model only picks the level. Aversionthat is not a valid semantic version gets a message-only proposal. - Accepting a bump rewrites only the top-level
version:line ofshard.yml(quotes and trailing comments kept) and includes it in the same commit. editlets you retype the message (enter keeps it) and pick another bump;noaborts and leaves your changes staged.- When the request fails (network, HTTP error, empty or invalid reply),
savestops with your changes staged and asks for-m MSG. - Outside a terminal (pipes, scripts, agents) nothing changes:
saverequires-m MSG. - The model defaults to
deepseek-flash(non-thinking, JSON output mode); override it with$PROJECT_LLM_MODEL. Diffs are sent to DeepSeek's API.
Remote repo
dev clone and dev remote require the GitHub CLI (gh), installed and authenticated.
dev cloneclones viagh repo cloneinto<dir>(default: the repository name) and runsdev openinside it;devis checked out fromorigin/devwhen it exists. Refuses inside a git repository or when<dir>exists.dev remoteresolves the GitHub repo fromorigin's URL, not the directory name.--visis a no-op when the visibility is already set, and prints the consequences of a change (lost stars and watchers, detached public forks, disabled push rulesets, exposed GitHub Actions history and logs).--delfetchesoriginwith tags, writes a backup bundle, warns about tags published onorigin(shards consumers lose those releases), then letsghprompt for the repo name as confirmation. It needs thedelete_repotoken scope (gh auth refresh -h github.com -s delete_repo). Local history and theoriginremote are kept;git remote remove originlets the next push create a new GitHub repo.
Release tags
When shard.yml on dev has a version, dev release creates an annotated tag v<version> on the new main commit (message: the release title) and pushes only that tag. Shards resolves dependency versions from these tags.
- Version guard: if
v<version>already exists locally or onoriginwith different content, the release is refused before anything changes — bumpversioninshard.ymlfirst, or pass--no-tag.deveditsversiononly when you accept a DeepSeek proposal duringdev savein a terminal. A tag with identical content is left as is. - Foreign tags:
dev openanddev releasewarn about tags onoriginthat are not reachable frommainordev(the mark of a recreated history). Shards never prunes deleted tags from its cache, so after such tags are removed, consumers must delete their cached copy under~/.cache/shards/. dev statusshows the version state: not yet released, released, released but changed since (bump before the next release), not pushed, outside this history, or origin unreachable.dev release --edit-titlemoves tags onmain's tip and keeps annotated tags annotated, with the new title as message.
Environment overrides: $PROJECT_MAIN (default: detected main/master), $PROJECT_DEV (default: dev), $PROJECT_REMOTE (default: directory name; use owner/name to override), $PROJECT_PUBLIC=1 (make auto-created remotes public instead of private), $PROJECT_BACKUP_DIR (default ~/.local/share/project/backups/<repo>/, falling back to the old ~/.local/share/gitflow/backups/<repo>/ when it exists), $PROJECT_WIDTH (help/graph wrap width; 0 disables), $PROJECT_TREE=branch|box (force graph glyph style), $DEEPSEEK_API_KEY (enables save proposals, find, explain, notes, and tok --exact), $PROJECT_LLM_MODEL (default: deepseek-flash).
History insight
find, explain and notes are read-only: they change nothing in the repository. They need $DEEPSEEK_API_KEY but not a terminal, so their output can be piped. Progress and token usage go to stderr; results go to stdout.
dev find <description>... [-n LIMIT] name the commit a description refers to (searches the last
LIMIT non-merge commits of dev, default 200)
dev explain [<rev> | <range>] explain a commit or range in plain language
(default: main..dev when dev has unreleased changes, else HEAD)
dev notes [<tag>] draft markdown release notes for v<version> (default: latest)
findsends subjects, dates and changed paths (--name-status), and prints the match, the reason, and thedev undo --to <sha>command to restore it; nothing is restored for you. A description of a state ("before I changed the help wrapping") resolves to the newest commit that has that state. An answer that is not among the searched commits is rejected.explaintakes any revision (HEAD~2, a tag, a sha) or range (v0.11.0..dev); merges are shown against their first parent.notesordersv<version>tags withSemanticVersion, diffs the tag against the previous release (or the empty tree for the first), and prints Breaking / Added / Changed / Fixed sections, e.g.dev notes > notes.md && gh release create v0.12.0 --notes-file notes.md.
tok
Estimates token counts for source code and text files, rendered as a directory tree.
dev tok [--exact] [<targets>...]
By default the estimate is offline (file size ÷ 4). --exact counts real tokens for $PROJECT_LLM_MODEL through the DeepSeek API: every file is sent as one request (8 in parallel, max_tokens 1), and the chat-template overhead measured by a one-character probe is subtracted from each prompt_tokens. Empty files count as 0 without a request; a file whose request fails falls back to the estimate with a note. This sends your files to DeepSeek and is billed as input tokens.
loc
Counts lines of code grouped by language, with a per-language breakdown of files, total / blank / comment / code lines, plus a grand total. Skips binary and hidden files; unrecognized text files are grouped as other.
dev loc [<targets>...]
chlog
Generates a changelog from the release history on main — one entry per release commit, newest first.
dev chlog [<branch>] [-n LIMIT]
Build and install
shards build dev # builds bin/dev
make install # builds src/tools/dev.cr into ~/.local/bin/dev (release)
# and copies SKILL.md to ~/.agents/skills/dev/
make uninstall # removes dev and any leftover project/tok/loc/chlog binaries
Requires Crystal >= 1.21.
dev
- 0
- 0
- 0
- 0
- 0
- about 1 hour ago
- October 13, 2026
MIT License
Tue, 13 Oct 2026 22:02:58 GMT