2026-05-03 09:07:45 +02:00
|
|
|
# Changelog
|
|
|
|
|
|
|
|
|
|
All notable changes to `@przeprogramowani/10x-cli` are documented in this file.
|
|
|
|
|
|
|
|
|
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
|
|
2026-06-20 11:41:53 +02:00
|
|
|
## [Unreleased]
|
|
|
|
|
|
2026-08-16 23:24:25 +02:00
|
|
|
### Changed
|
|
|
|
|
|
2026-08-20 10:10:45 +02:00
|
|
|
- **Windsurf is now Devin Desktop.** The tool selector uses `devin-desktop`,
|
|
|
|
|
writes new artifacts under `.devin/`, and uses root `AGENTS.md` for course
|
|
|
|
|
rules. The former `windsurf` ID and `.windsurf/` markers remain supported for
|
|
|
|
|
config compatibility, detection, and artifact migration.
|
2026-08-16 23:24:25 +02:00
|
|
|
- **`10x bench-kit` is generally available.** The `TENX_CLI_EXPERIMENTAL`
|
|
|
|
|
opt-in is gone: `init` and `update` are registered unconditionally, appear
|
|
|
|
|
in `--help`, and are documented in the README. The `experimental_locked`
|
|
|
|
|
error envelope no longer exists (the gating module has been removed).
|
|
|
|
|
|
2026-06-20 11:41:53 +02:00
|
|
|
### Added
|
|
|
|
|
|
feat(tool-profile): add Kiro as a supported tool profile (#51)
Register a `kiro` profile that writes artifacts under `.kiro/` (skills,
prompts, config templates) and co-owns the root `AGENTS.md` for course
rules alongside codex, devin-desktop and generic. Content is delivered in
the generic variant because the delivery API exposes no `kiro` transform
yet.
Auto-detection reports Kiro from `.kiro/.10x-cli-manifest.json`,
`.kiro/steering/`, `.kiro/specs/`, `.kiro/hooks/`, `.kiro/settings/` or a
bare `.kiro/` directory. Every branch is `strong`: the directory name is
Kiro-specific with no plausible false positive, so a Kiro workspace never
loses the `AGENTS.md` confidence tie to codex and `PROFILE_ORDER` needs no
reshuffle. The profile takes its place in the resolution order ahead of
generic.
Extend `--tool` help text for `get` and `sync`, document the new paths,
the `.kiro/config-templates/` staging caveat and the exact limits of
`AGENTS.md` co-ownership (byte-identical rules only, so `kiro` pairs with
generic but reports `incompatible_shared_owner` next to codex or
devin-desktop) in the platform support reference and README, and cover the
profile in the detection, profile, tool-switch, writer and install-contract
test suites — including the divergent-content case that must fail closed.
The bundled `skills/10x-cli-guide/SKILL.md` is deliberately left unchanged:
`helpers install` is create-only and exits 1 on a byte difference, so a
documentation-only edit there would break every existing install.
2026-09-18 11:56:57 +02:00
|
|
|
- **Kiro is a supported tool profile.** `--tool kiro` writes artifacts under
|
|
|
|
|
`.kiro/`, uses root `AGENTS.md` for course rules, and is auto-detected from
|
|
|
|
|
`.kiro/steering/`, `.kiro/specs/`, `.kiro/hooks/`, `.kiro/settings/` or a bare
|
|
|
|
|
`.kiro/` directory. Content is
|
|
|
|
|
delivered in the generic variant.
|
2026-06-20 11:41:53 +02:00
|
|
|
- **`10x sync` — bulk download & update with change visibility.** One command to
|
|
|
|
|
download every unlocked lesson (`--all`) or refresh the ones you've already
|
|
|
|
|
downloaded (default), with a report of what changed upstream. Each not-updated
|
|
|
|
|
resource prints the exact `10x get …` command to take it; `--force` takes all
|
|
|
|
|
upstream updates over local edits, `--dry-run` previews without writing. Exit
|
|
|
|
|
code is worst-outcome (`1` if any lesson errored, else `0`).
|
|
|
|
|
- Unchanged lessons are skipped **without a download**: the catalog now advertises
|
|
|
|
|
a per-lesson `contentHash` (added in `@przeprogramowani/10x-toolkit`), compared
|
|
|
|
|
digest-vs-digest against the value stored in the manifest at last apply. Older
|
|
|
|
|
backends/manifests without a digest fall back to always-fetch.
|
|
|
|
|
- `planBundle()` — a pure, non-writing, non-prompting writer planner that classifies
|
|
|
|
|
per-file actions + conflicts; `applyBundle` now consumes it so preview and apply
|
|
|
|
|
can't diverge.
|
|
|
|
|
- Manifest `lessons[].catalogContentHash` (additive, optional) and
|
|
|
|
|
`LessonSummary.contentHash` (optional) carry the per-lesson digest. Change
|
|
|
|
|
visibility covers skills and prompts (configs are create-only; rules are
|
|
|
|
|
sentinel-managed).
|
|
|
|
|
|
2026-05-03 09:07:45 +02:00
|
|
|
## [1.0.0] - 2026-05-03
|
|
|
|
|
|
|
|
|
|
### Breaking changes
|
|
|
|
|
|
|
|
|
|
This release upgrades to the directory-shaped skill bundle defined by the
|
|
|
|
|
delivery API at `@przeprogramowani/10x-toolkit`. **CLIs older than 1.0.0 cannot
|
|
|
|
|
parse bundles produced after the API deploy**, and 1.0.0 cannot consume the
|
|
|
|
|
old bundle shape. Both repos must roll forward together.
|
|
|
|
|
|
|
|
|
|
- **Skill bundles ship as full directories.** A skill is now `{ name, files: [{ path, content, executable? }] }`
|
|
|
|
|
rather than `{ name, content }`. Every file under the skill directory in
|
|
|
|
|
`@przeprogramowani/ai-artifacts` (e.g. `scripts/`, `references/`) materializes
|
|
|
|
|
on disk with its executable bit preserved when set. Running `10x get m1l1`
|
|
|
|
|
now writes `.claude/skills/<name>/SKILL.md`, `.claude/skills/<name>/scripts/check-context.sh`
|
|
|
|
|
(with `+x`), and any other files under the source skill directory.
|
|
|
|
|
- **`ArtifactResponse` is a discriminated union.** `/api/artifacts/.../skills/:name`
|
|
|
|
|
returns `{ type: "skills", name, files, universalContent? }`; prompts/rules/configs
|
|
|
|
|
still return `{ type, name, content }`. Code reading `result.data.content` for
|
|
|
|
|
skills will not type-check.
|
|
|
|
|
- **Manifest schema bumped to v2.** `files.skills` is now a record keyed by
|
|
|
|
|
skill name → `{ files: string[] }` (relative paths under the skill dir).
|
|
|
|
|
v1 manifests (skills as `string[]`) are read as `null` — treated as
|
|
|
|
|
no-prior-state for one cleanup cycle, then the v2 manifest takes over on
|
|
|
|
|
the next apply. No migration script.
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
|
|
|
|
- **Per-file removal within a retained skill.** When upstream drops a file from
|
|
|
|
|
an existing skill, `10x get` removes the local copy and prunes the now-empty
|
|
|
|
|
parent directory; the skill directory itself stays put for subsequent applies.
|
|
|
|
|
- **Path-traversal guard for skill files.** `assertSafeSkillFilePath` rejects
|
|
|
|
|
empty paths, absolute paths, drive prefixes, `..` segments, backslash
|
|
|
|
|
separators, and Windows-reserved names (CON/PRN/...). The writer aborts
|
|
|
|
|
before any filesystem mutation when a bundle is tampered.
|
|
|
|
|
- **Print-mode notice for multi-file skills.** `10x get ... --print --type skills [--name X]`
|
|
|
|
|
emits SKILL.md to stdout (so redirects like `> /tmp/SKILL.md` capture only
|
|
|
|
|
that), and writes `Note: skill "<name>" has N additional files not shown in
|
|
|
|
|
--print: ...\nRun without --print to materialize all files.` to stderr.
|
|
|
|
|
JSON mode is unchanged; the full `files[]` array is in the response.
|
|
|
|
|
- **Per-file actions in `WriteResult.skills`.** `result.skills[i]` is now
|
|
|
|
|
`{ name, files: [{ path, absolutePath, action }] }` instead of `{ name, path, action }`.
|
|
|
|
|
The `--json` output reflects the same shape; consumers reading per-skill
|
|
|
|
|
status need to walk the `files` array.
|
|
|
|
|
|
|
|
|
|
### Changed
|
|
|
|
|
|
|
|
|
|
- **`ToolProfile.skillDir(name)`** is a new required field on every profile,
|
|
|
|
|
returning the skill directory path (without the `/SKILL.md` suffix). The
|
|
|
|
|
existing `skillPath(name)` is unchanged for callers that need the SKILL.md
|
|
|
|
|
file specifically.
|
|
|
|
|
- **`tool-switch` migration walks every file under each skill directory** —
|
|
|
|
|
`migrateArtifacts` and `deleteArtifacts` no longer assume a single file
|
|
|
|
|
per skill.
|
|
|
|
|
|
|
|
|
|
### Removed
|
|
|
|
|
|
|
|
|
|
- Nothing student-facing was removed. Old `ArtifactWrite { name, path, action }`
|
|
|
|
|
entries in `WriteResult.skills` are replaced by the per-file `SkillWrite`
|
|
|
|
|
shape described above.
|