feat(profiles): choose which profile a new profile clones from - #2309
Open
twuijri wants to merge 1 commit into
Open
feat(profiles): choose which profile a new profile clones from#2309twuijri wants to merge 1 commit into
twuijri wants to merge 1 commit into
Conversation
`hermes profile create --clone` reads `active_profile`, so the Web UI could
only ever clone the profile you happened to be standing in. Switching profiles
first, just to clone a different one, is a detour the UI should not require.
The create dialog now asks for a source profile, defaulting to the active one,
so the previous one-switch flow is unchanged.
Server:
- `POST /api/hermes/profiles` accepts `cloneFrom`; `clone: true` without it
keeps meaning "the active profile"
- source === active still goes through the CLI's `--clone`, untouched
- other sources create an empty profile and copy the same set `--clone`
copies (config.yaml / .env / SOUL.md / skills), then run the existing
post-processing with the source made explicit
- `copyModelProviderAuthForClone` takes the source profile instead of
assuming the active one
- the source is validated (name shape, existence, reserved names, user
access) before anything is created
Model providers and their keys come across as before; smart clone cleanup
still strips exclusive platform credentials so two profiles never share one
bot token.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
twuijri
force-pushed
the
clone-from-any-profile
branch
from
August 2, 2026 14:17
f86e100 to
c14da86
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Creating a profile can clone one — but only ever the profile you happen to be standing in, because
hermes profile create --clonetakes its source fromactive_profileand has no flag for anything else. Cloningresearchwhile you are inworkmeans switching toresearch, creating, and switching back. This adds a source picker instead.Server
POST /api/hermes/profilesacceptscloneFrom.clone: truewith nocloneFromstill means "the active profile", so existing callers are unaffected.--clonedoes the work, exactly as today.--clonecopies:config.yaml,.env,SOUL.md,skills/. That list lives in one named constant next to the comment documenting the CLI's behaviour, so the two stay together if the CLI ever changes.Either way the existing post-processing runs afterwards, with the source now explicit rather than assumed:
copyModelProviderAuthForClone(name, source)— takes the source profile instead of readingactive_profile. Same policy as before: only the auth keys the clonedmodel.providerneeds.smartCloneCleanup(name)— unchanged, so a clone never carries a second copy of a Telegram or Slack token into a profile that would then fight the source for the platform lock.The source is validated before anything is created: name shape, existence, reserved names, and the requesting user's profile access — a non-admin cannot clone a profile they cannot see.
Client
ProfileCreateModal.vuegains anNSelectunder the switch.createProfile(name, cloneFrom)replacescreateProfile(name, clone)through the store and API layer. Four new i18n keys replaceprofiles.cloneFromCurrent, translated in all eleven locales.Tests
tests/server/profiles-routes.test.ts(5 new) andtests/client/profile-create-modal.test.ts(4 new):.envis still stripped--clone;clone: truealone still means the active profilenullwhen cloning is offI reverted the controller and confirmed all five server tests fail without the change.
docs/openapi.jsonis regenerated output, not a hand edit.One thing worth deciding, not decided here
OAuth logins in
auth.jsonstill only follow the provider named inmodel.provider. If a profile has several OAuth providers signed in, the clone gets one. That is your existing policy and I left it alone — happy to widen it in a follow-up if you would rather a clone arrive fully signed in.