# NousResearch/hermes-agent · Clone profile from any source via dropdown

## Open now

- Nothing open on GitHub.

These issues and PRs relate to adding or requesting a feature that allows cloning a new profile from any existing profile, replacing a checkbox with a dropdown selector. The theme is consistent across a dashboard UI change and a corresponding profile backend feature.

## TL;DR

- 3 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 1 PR(s) closed without merging.
- A fix was merged to main in PR #45630. Verify it addresses your case.
- **Recommended:** read PR #45630 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-45630`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.67`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #23746: \[Feature\]: Dashboard — clone new profile from any profile (dropdown instead of checkbox)

## Prior & competing PRs

- **#45630: feat(profile): clone profiles from any source**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `apps/desktop/src/app/chat/sidebar/profile-switcher.tsx`, `apps/desktop/src/app/profiles/create-profile-dialog.tsx`, `apps/desktop/src/app/profiles/index.tsx`, `apps/desktop/src/i18n/en.ts`, `apps/desktop/src/i18n/ja.ts`, `apps/desktop/src/i18n/types.ts`, `apps/desktop/src/i18n/zh-hant.ts`, `apps/desktop/src/i18n/zh.ts`, `apps/desktop/src/types/hermes.ts`, `docs/design/profile-builder.md`, `hermes_cli/main.py`, `hermes_cli/profiles.py`, `hermes_cli/subcommands/profile.py`, `hermes_cli/web_server.py`, `scripts/release.py`, `tests/hermes_cli/test_web_server.py`, `web/src/i18n/af.ts`, `web/src/i18n/de.ts`, `web/src/i18n/en.ts`, `web/src/i18n/es.ts` (+24 more)
  - fix hunks:
  - `apps/desktop/src/app/chat/sidebar/profile-switcher.tsx`

    ```diff
    @@ -284,6 +284,7 @@ export function ProfileRail() {
               selectProfile(name)
             }}
             open={createOpen}
    +        profiles={profiles}
           />
     
           <RenameProfileDialog
    ```
  - `apps/desktop/src/app/profiles/create-profile-dialog.tsx`

    ```diff
    @@ -2,14 +2,15 @@ import { useEffect, useState } from 'react'
     
     import { ActionStatus } from '@/components/ui/action-status'
     import { Button } from '@/components/ui/button'
    -import { Checkbox } from '@/components/ui/checkbox'
     import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
     import { Input } from '@/components/ui/input'
    +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
     import { Textarea } from '@/components/ui/textarea'
     import { createProfile, updateProfileSoul } from '@/hermes'
     import { useI18n } from '@/i18n'
     import { AlertTriangle } from '@/lib/icons'
     import { cn } from '@/lib/utils'
    +import type { ProfileInfo } from '@/types/hermes'
     
     const PROFILE_NAME_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/
     
    ```

    ```diff
    @@ -23,16 +24,18 @@ export function isValidProfileName(name: string): boolean {
     export function CreateProfileDialog({
       onClose,
       onCreated,
    -  open
    +  open,
    +  profiles = []
     }: {
       onClose: () => void
       onCreated?: (name: string) => Promise<void> | void
       open: boolean
    +  profiles?: ProfileInfo[]
     }) {
       const { t } = useI18n()
       const p = t.profiles
       const [name, setName] = useState('')
    -  const [cloneFromDefault, setCloneFromDefault] = useState(true)
    +  const [cloneFrom, setCloneFrom] = useState<null | string>('default')
       const [soul, setSoul] = useState('')
       const [status, setStatus] = useState<'done' | 'idle' | 'saving'>('idle')
       const [error, setError] = useState<null | string>(null)
    ```

    ```diff
    @@ -43,7 +46,7 @@ export function CreateProfileDialog({
         }
     
         setName('')
    -    setCloneFromDefault(true)
    +    setCloneFrom('default')
         setSoul('')
         setError(null)
         setStatus('idle')
    ```

    ```diff
    @@ -66,7 +69,7 @@ export function CreateProfileDialog({
         setError(null)
     
         try {
    -      await createProfile({ name: trimmed, clone_from_default: cloneFromDefault })
    +      await createProfile({ name: trimmed, clone_from: cloneFrom })
     
           if (soul.trim()) {
             await updateProfileSoul(trimmed, soul)
    ```

    ```diff
    @@ -107,17 +110,25 @@ export function CreateProfileDialog({
                 </p>
               </div>
     
    -          <label className="flex cursor-pointer select-none items-start gap-2.5 px-0.5 py-1">
    -            <Checkbox
    -              checked={cloneFromDefault}
    -              className="mt-0.5 shrink-0"
    -              onCheckedChange={checked => setCloneFromDefault(checked === true)}
    -            />
    -            <span className="grid gap-0.5 leading-snug">
    -              <span className="text-sm font-medium">{p.cloneFromDefault}</span>
    -              <span className="text-xs text-muted-foreground">{p.cloneFromDefaultDesc}</span>
    -            </span>
    -          </label>
    +          <div className="grid gap-1.5">
    +            <label className="text-xs font-medium" htmlFor="new-profile-clone-from">
    +              {p.cloneFrom}
    +            </label>
    +            <Select onValueChange={value => setCloneFrom(value === '__none__' ? null : value)} value={cloneFrom ?? '__none__'}>
    +              <SelectTrigger className="h-9 rounded-md" id="new-profile-clone-from">
    +                <SelectValue />
    +              </SelectTrigger>
    +              <SelectContent>
    +                <SelectItem value="__none__">{p.cloneFromNone}</SelectItem>
    +                {profiles.map(profile => (
    +                  <SelectItem key={profile.name} value={profile.name}>
    +                    {profile.name}
    +                  </SelectItem>
    +                ))}
    +              </SelectContent>
    +            </Select>
    +            <p className="text-xs text-muted-foreground">{p.cloneFromDesc}</p>
    +          </div>
     
               <div className="grid gap-1.5">
                 <label className="text-xs font-medium" htmlFor="new-profile-soul">
    ```

    ```diff
    @@ -127,7 +138,7 @@ export function CreateProfileDialog({
                   className="min-h-28 font-mono text-xs leading-5"
                   id="new-profile-soul"
                   onChange={event => setSoul(event.target.value)}
    -              placeholder={p.soulPlaceholder(cloneFromDefault ? p.soulPlaceholderCloned : p.soulPlaceholderEmpty)}
    +              placeholder={p.soulPlaceholder(cloneFrom ? p.soulPlaceholderCloned : p.soulPlaceholderEmpty)}
                   value={soul}
                 />
               </div>
    ```
  - `apps/desktop/src/app/profiles/index.tsx`

    ```diff
    @@ -12,6 +12,7 @@ import {
       DialogTitle
     } from '@/components/ui/dialog'
     import { Input } from '@/components/ui/input'
    +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
     import { Textarea } from '@/components/ui/textarea'
     import {
       createProfile,
    ```

    ```diff
    @@ -82,14 +83,14 @@ export function ProfilesView({ onClose }: ProfilesViewProps) {
       }, [profiles, selectedName])
     
       const handleCreate = useCallback(
    -    async (name: string, cloneFromDefault: boolean) => {
    +    async (name: string, cloneFrom: null | string) => {
           const trimmed = name.trim()
     
           if (!isValidProfileName(trimmed)) {
             throw new Error(p.nameHint)
           }
     
    -      await createProfile({ name: trimmed, clone_from_default: cloneFromDefault })
    +      await createProfile({ name: trimmed, clone_from: cloneFrom })
           notify({ kind: 'success', title: p.created, message: trimmed })
           setSelectedName(trimmed)
           await refresh()
    ```

    ```diff
    @@ -180,8 +181,9 @@ export function ProfilesView({ onClose }: ProfilesViewProps) {
     
           <CreateProfileDialog
               onClose={() => setCreateOpen(false)}
    -          onCreate={async (name, cloneFromDefault) => handleCreate(name, cloneFromDefault)}
    +          onCreate={async (name, cloneFrom) => handleCreate(name, cloneFrom)}
               open={createOpen}
    +          profiles={profiles ?? []}
             />
     
             <Dialog onOpenChange={open => !open && !deleting && setPendingDelete(null)} open={pendingDelete !== null}>
    ```

    ```diff
    @@ -453,16 +455,18 @@ function SoulEditor({ profileName }: { profileName: string }) {
     function CreateProfileDialog({
       onClose,
       onCreate,
    -  open
    +  open,
    +  profiles
     }: {
       onClose: () => void
    -  onCreate: (name: string, cloneFromDefault: boolean) => Promise<void>
    +  onCreate: (name: string, cloneFrom: null | string) => Promise<void>
       open: boolean
    +  profiles: ProfileInfo[]
     }) {
       const { t } = useI18n()
       const p = t.profiles
       const [name, setName] = useState('')
    -  const [cloneFromDefault, setCloneFromDefault] = useState(true)
    +  const [cloneFrom, setCloneFrom] = useState<null | string>('default')
       const [saving, setSaving] = useState(false)
       const [error, setError] = useState<null | string>(null)
     
    ```

    ```diff
    @@ -472,7 +476,7 @@ function CreateProfileDialog({
         }
     
         setName('')
    -    setCloneFromDefault(true)
    +    setCloneFrom('default')
         setError(null)
         setSaving(false)
       }, [open])
    ```

    ```diff
    @@ -493,7 +497,7 @@ function CreateProfileDialog({
         setError(null)
     
         try {
    -      await onCreate(trimmed, cloneFromDefault)
    +      await onCreate(trimmed, cloneFrom)
           onClose()
         } catch (err) {
           setError(err instanceof Error ? err.message : p.failedCreate)
    ```

    ```diff
    @@ -528,18 +532,25 @@ function CreateProfileDialog({
                 </p>
               </div>
     
    -          <label className="flex cursor-pointer items-center gap-2 rounded-md border border-border/40 bg-background/50 px-3 py-2 text-sm">
    -            <input
    -              checked={cloneFromDefault}
    -              className="size-4 accent-primary"
    -              onChange={event => setCloneFromDefault(event.target.checked)}
    -              type="checkbox"
    -            />
    -            <span>
    -              <span className="font-medium">{p.cloneFromDefault}</span>
    -              <span className="ml-2 text-xs text-muted-foreground">{p.cloneFromDefaultDesc}</span>
    -            </span>
    -          </label>
    +          <div className="grid gap-1.5">
    +            <label className="text-xs font-medium" htmlFor="new-profile-clone-from">
    +              {p.cloneFrom}
    +            </label>
    +            <Select onValueChange={value => setCloneFrom(value === '__none__' ? null : value)} value={cloneFrom ?? '__none__'}>
    +              <SelectTrigger className="h-9 rounded-md" id="new-profile-clone-from">
    +                <SelectValue />
    +              </SelectTrigger>
    +              <SelectContent>
    +                <SelectItem value="__none__">{p.cloneFromNone}</SelectItem>
    +                {profiles.map(profile => (
    +                  <SelectItem key={profile.name} value={profile.name}>
    +                    {profile.name}
    +                  </SelectItem>
    +                ))}
    +              </SelectContent>
    +            </Select>
    +            <p className="text-xs text-muted-foreground">{p.cloneFromDesc}</p>
    +          </div>
     
               {error && (
                 <div className="flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive">
    ```
  - `apps/desktop/src/i18n/en.ts`

    ```diff
    @@ -903,6 +903,9 @@ export const en: Translations = {
         deleting: 'Deleting...',
         createDesc: 'Profiles are independent Hermes environments: separate config, skills, and SOUL.md.',
         nameLabel: 'Name',
    +    cloneFrom: 'Clone from',
    +    cloneFromNone: 'None (blank)',
    +    cloneFromDesc: 'Copies config, skills, and SOUL.md from the selected source profile.',
         cloneFromDefault: 'Clone from default',
         cloneFromDefaultDesc: 'Copy config, skills, and SOUL.md from your default profile.',
         invalidName: hint => `Invalid name. ${hint}`,
    ```
  - `apps/desktop/src/i18n/ja.ts`

    ```diff
    @@ -1041,6 +1041,9 @@ export const ja = defineLocale({
         deleting: '削除中...',
         createDesc: 'プロファイルは独立した Hermes 環境です：設定、スキル、SOUL.md が別々になります。',
         nameLabel: '名前',
    +    cloneFrom: '複製元',
    +    cloneFromNone: 'なし（空）',
    +    cloneFromDesc: '選択したプロファイルから設定、スキル、SOUL.md をコピーします。',
         cloneFromDefault: 'デフォルトプロファイルから設定を複製',
         cloneFromDefaultDesc: 'デフォルトプロファイルから設定、スキル、SOUL.md をコピーします。',
         invalidName: hint => `無効なプロファイル名。${hint}`,
    ```
  - `apps/desktop/src/i18n/types.ts`

    ```diff
    @@ -695,6 +695,9 @@ export interface Translations {
         deleting: string
         createDesc: string
         nameLabel: string
    +    cloneFrom: string
    +    cloneFromNone: string
    +    cloneFromDesc: string
         cloneFromDefault: string
         cloneFromDefaultDesc: string
         invalidName: (hint: string) => string
    ```
  - `apps/desktop/src/i18n/zh-hant.ts`

    ```diff
    @@ -999,6 +999,9 @@ export const zhHant = defineLocale({
         deleting: '刪除中…',
         createDesc: '設定檔是獨立的 Hermes 環境：各自擁有獨立的設定、技能和 SOUL.md。',
         nameLabel: '名稱',
    +    cloneFrom: '複製來源',
    +    cloneFromNone: '無（空白）',
    +    cloneFromDesc: '從選取的來源設定檔複製設定、技能和 SOUL.md。',
         cloneFromDefault: '從預設設定檔複製設定',
         cloneFromDefaultDesc: '從您的預設設定檔複製設定、技能和 SOUL.md。',
         invalidName: hint => `設定檔名稱無效。${hint}`,
    ```
  - `apps/desktop/src/i18n/zh.ts`

    ```diff
    @@ -1092,6 +1092,9 @@ export const zh: Translations = {
         deleting: '删除中…',
         createDesc: '配置档案是相互独立的 Hermes 环境：各自拥有独立的配置、技能和 SOUL.md。',
         nameLabel: '名称',
    +    cloneFrom: '克隆来源',
    +    cloneFromNone: '无（空白）',
    +    cloneFromDesc: '从选中的来源配置档案复制配置、技能和 SOUL.md。',
         cloneFromDefault: '从默认档案克隆',
         cloneFromDefaultDesc: '从你的默认配置档案复制配置、技能和 SOUL.md。',
         invalidName: hint => `名称无效。${hint}`,
    ```
  - `apps/desktop/src/types/hermes.ts`

    ```diff
    @@ -470,7 +470,7 @@ export interface CronJobUpdates {
     
     export interface ProfileCreatePayload {
       clone_all?: boolean
    -  clone_from?: string
    +  clone_from?: null | string
       clone_from_default?: boolean
       name: string
       no_skills?: boolean
    ```
  - `docs/design/profile-builder.md`

    ```diff
    @@ -85,6 +85,8 @@ Extend `ProfileCreate` and the create endpoint — no new endpoints, no rewrite:
     ```python
     class ProfileCreate(BaseModel):
         name: str
    +    clone_from: Optional[str] = None
    +    # Backward compatibility for older dashboard/desktop clients.
         clone_from_default: bool = False
         clone_all: bool = False
         no_skills: bool = False
    ```
  - `hermes_cli/main.py`

    ```diff
    @@ -9860,19 +9860,20 @@ def cmd_profile(args):
     
             try:
                 clone_from = getattr(args, "clone_from", None)
    +            clone_config = clone or clone_from is not None
     
                 profile_dir = create_profile(
                     name=name,
                     clone_from=clone_from,
                     clone_all=clone_all,
    -                clone_config=clone,
    +                clone_config=clone_config,
                     no_alias=no_alias,
                     no_skills=no_skills,
                     description=getattr(args, "description", None),
                 )
                 print(f"\nProfile '{name}' created at {profile_dir}")
     
    -            if clone or clone_all:
    +            if clone_config or clone_all:
                     source_label = (
                         getattr(args, "clone_from", None) or get_active_profile_name()
                     )
    ```

    ```diff
    @@ -9886,8 +9887,8 @@ def cmd_profile(args):
                             f"Cloned config, .env, SOUL.md, and skills from {source_label}."
                         )
     
    -            # Auto-clone Honcho config for the new profile (only with --clone/--clone-all)
    -            if clone or clone_all:
    +            # Auto-clone Honcho config for the new profile (only with clone operations)
    +            if clone_config or clone_all:
                     try:
                         from plugins.memory.honcho.cli import clone_honcho_for_profile
     
    ```

    ```diff
    @@ -9896,10 +9897,10 @@ def cmd_profile(args):
                     except Exception:
                         pass  # Honcho plugin not installed or not configured
     
    -            # Seed bundled skills (skip if --clone-all already copied them, or
    -            # if --no-skills was passed — in which case seed_profile_skills()
    -            # honors the marker file and returns skipped_opt_out=True).
    -            if not clone_all:
    +            # Seed bundled skills for fresh profiles only. Clone operations
    +            # already copied the source profile's skills, including any
    +            # user-installed or intentionally removed skills.
    +            if not (clone_config or clone_all):
                     result = seed_profile_skills(profile_dir)
                     if result and result.get("skipped_opt_out"):
                         print(
    ```
  - `hermes_cli/profiles.py`

    ```diff
    @@ -784,9 +784,9 @@ def create_profile(
         Path
             The newly created profile directory.
         """
    -    if no_skills and (clone_config or clone_all):
    +    if no_skills and (clone_from is not None or clone_config or clone_all):
             raise ValueError(
    -            "--no-skills is mutually exclusive with --clone / --clone-all "
    +            "--no-skills is mutually exclusive with --clone / --clone-from / --clone-all "
                 "(cloning explicitly copies skills from the source profile)."
             )
         canon = normalize_profile_name(name)
    ```
  - `hermes_cli/subcommands/profile.py`

    ```diff
    @@ -35,17 +35,17 @@ def build_profile_parser(subparsers, *, cmd_profile: Callable) -> None:
         profile_create.add_argument(
             "--clone",
             action="store_true",
    -        help="Copy config.yaml, .env, SOUL.md from active profile",
    +        help="Copy config.yaml, .env, SOUL.md, and skills from active profile",
         )
         profile_create.add_argument(
             "--clone-all",
             action="store_true",
    -        help="Full copy of active profile (all state)",
    +        help="Full copy of active profile (all state, excluding per-profile history)",
         )
         profile_create.add_argument(
             "--clone-from",
             metavar="SOURCE",
    -        help="Source profile to clone from (default: active)",
    +        help="Source profile to clone from; implies --clone unless --clone-all is set",
         )
         profile_create.add_argument(
             "--no-alias", action="store_true", help="Skip wrapper script creation"
    ```
  - `hermes_cli/web_server.py`

    ```diff
    @@ -8493,15 +8493,13 @@ def _run():
     
     class ProfileCreate(BaseModel):
         name: str
    +    clone_from: Optional[str] = None
    +    # Backward compatibility for older dashboard/desktop clients. New clients
    +    # send clone_from="default" (or another profile name) explicitly.
         clone_from_default: bool = False
         clone_all: bool = False
         no_skills: bool = False
         description: Optional[str] = None
    -    # Explicit source profile to clone from (e.g. duplicating an existing
    -    # profile). When set, it takes precedence over ``clone_from_default``,
    -    # which always sources from "default". ``clone_all`` still selects a full
    -    # state copytree vs. a config/skills/SOUL copy.
    -    clone_from: Optional[str] = None
         provider: Optional[str] = None
         model: Optional[str] = None
         # Profile-builder additions — all optional, all applied best-effort AFTER
    ```

    ```diff
    @@ -8773,10 +8771,16 @@ async def create_profile_endpoint(body: ProfileCreate):
             clone = True
             clone_from = explicit_source
             clone_config = not body.clone_all
    +    elif body.clone_all:
    +        # Preserve the dashboard's historical clone-all behavior: a full-copy
    +        # request with no explicit dropdown source copies from default.
    +        clone = True
    +        clone_from = "default"
    +        clone_config = False
         else:
    -        clone = body.clone_from_default or body.clone_all
    +        clone = body.clone_from_default
             clone_from = "default" if clone else None
    -        clone_config = body.clone_from_default and not body.clone_all
    +        clone_config = clone
         try:
             path = profiles_mod.create_profile(
                 name=body.name,
    ```
  - `scripts/release.py`

    ```diff
    @@ -494,6 +494,7 @@
         "[redacted:email]": "nik1t7n",
         "90299797+nik1t7n@users.noreply.github.com": "nik1t7n",
         "[redacted:email]": "suncokret12",
    +    "[redacted:email]": "WompaJango",
         "[redacted:email]": "mioimotoai-lgtm",
         "[redacted:email]": "heyitsaamir",
         "[redacted:email]": "johnncenae",
    ```
  - `tests/hermes_cli/test_web_server.py`

    ```diff
    @@ -2633,7 +2633,7 @@ def test_profiles_create_creates_wrapper_alias_when_safe(self, monkeypatch, tmp_
     
             resp = self.client.post(
                 "/api/profiles",
    -            json={"name": "writer", "clone_from_default": False},
    +            json={"name": "writer", "clone_from": None},
             )
     
             assert resp.status_code == 200
    ```

    ```diff
    @@ -2641,7 +2641,7 @@ def test_profiles_create_creates_wrapper_alias_when_safe(self, monkeypatch, tmp_
             assert wrapper_path.exists()
             assert wrapper_path.read_text() == '#!/bin/sh\nexec hermes -p writer "$@"\n'
     
    -    def test_profiles_create_with_clone_from_default_copies_default_skills(self, monkeypatch):
    +    def test_profiles_create_with_clone_from_copies_source_skills(self, monkeypatch):
             from hermes_constants import get_hermes_home
             import hermes_cli.profiles as profiles_mod
     
    ```

    ```diff
    @@ -2652,7 +2652,7 @@ def test_profiles_create_with_clone_from_default_copies_default_skills(self, mon
     
             resp = self.client.post(
                 "/api/profiles",
    -            json={"name": "cloned", "clone_from_default": True},
    +            json={"name": "cloned", "clone_from": "default"},
             )
     
             assert resp.status_code == 200
    ```

    ```diff
    @@ -2685,6 +2685,28 @@ def test_profiles_create_with_clone_from_duplicates_source(self, monkeypatch):
             )
             assert cloned_skill.exists()
     
    +    def test_profiles_create_clone_all_from_named_source(self, monkeypatch):
    +        from hermes_constants import get_hermes_home
    +        import hermes_cli.profiles as profiles_mod
    +
    +        monkeypatch.setattr(profiles_mod, "create_wrapper_script", lambda name: None)
    +
    +        assert self.client.post("/api/profiles", json={"name": "full-src"}).status_code == 200
    +        source_dir = get_hermes_home() / "profiles" / "full-src"
    +        (source_dir / "config.yaml").write_text("model:\n  provider: source-only\n", encoding="utf-8")
    +        (source_dir / "workspace" / "artifact.txt").parent.mkdir(parents=True, exist_ok=True)
    +        (source_dir / "workspace" / "artifact.txt").write_text("copied", encoding="utf-8")
    +
    +        resp = self.client.post(
    +            "/api/profiles",
    +            json={"name": "full-copy", "clone_from": "full-src", "clone_all": True},
    +        )
    +
    +        assert resp.status_code == 200
    +        target_dir = get_hermes_home() / "profiles" / "full-copy"
    +        assert (target_dir / "config.yaml").read_text(encoding="utf-8") == "model:\n  provider: source-only\n"
    +        assert (target_dir / "workspace" / "artifact.txt").read_text(encoding="utf-8") == "copied"
    +
         def test_profiles_create_without_clone_seeds_bundled_skills(self, monkeypatch):
             from hermes_constants import get_hermes_home
             import hermes_cli.profiles as profiles_mod
    ```

    ```diff
    @@ -2701,7 +2723,7 @@ def fake_seed(profile_dir, quiet=False):
     
             resp = self.client.post(
                 "/api/profiles",
    -            json={"name": "fresh", "clone_from_default": False},
    +            json={"name": "fresh", "clone_from": None},
             )
     
             assert resp.status_code == 200
    ```
  - `web/src/i18n/af.ts`

    ```diff
    @@ -286,8 +286,8 @@ export const af: Translations = {
         nameRequired: "Naam word vereis",
         nameRule:
           "Slegs kleinletters, syfers, _ en -; moet met 'n letter of syfer begin; tot 64 karakters.",
    -    invalidName: "Ongeldige profielnaam",
    -    cloneFromDefault: "Kloon konfigurasie vanaf verstekprofiel",
    +    invalidName: "Ongeldige profielnaam",    cloneFrom: "Kloon konfigurasie vanaf profiel",
    +    cloneFromNone: "Geen (leeg)",
         allProfiles: "Profiele",
         noProfiles: "Geen profiele gevind nie.",
         defaultBadge: "verstek",
    ```
  - `web/src/i18n/de.ts`

    ```diff
    @@ -286,8 +286,8 @@ export const de: Translations = {
         nameRequired: "Name ist erforderlich",
         nameRule:
           "Nur Kleinbuchstaben, Ziffern, _ und -; muss mit einem Buchstaben oder einer Ziffer beginnen; maximal 64 Zeichen.",
    -    invalidName: "Ungültiger Profilname",
    -    cloneFromDefault: "Konfiguration vom Standardprofil klonen",
    +    invalidName: "Ungültiger Profilname",    cloneFrom: "Konfiguration klonen von",
    +    cloneFromNone: "Keine (leer)",
         allProfiles: "Profile",
         noProfiles: "Keine Profile gefunden.",
         defaultBadge: "Standard",
    ```
  - `web/src/i18n/en.ts`

    ```diff
    @@ -297,7 +297,8 @@ export const en: Translations = {
         nameRule:
           "Lowercase letters, digits, _ and - only; must start with a letter or digit; up to 64 characters.",
         invalidName: "Invalid profile name",
    -    cloneFromDefault: "Clone config from default profile",
    +    cloneFrom: "Clone config from",
    +    cloneFromNone: "None (blank)",
         allProfiles: "Profiles",
         noProfiles: "No profiles found.",
         defaultBadge: "default",
    ```
  - `web/src/i18n/es.ts`

    ```diff
    @@ -287,7 +287,8 @@ export const es: Translations = {
         nameRule:
           "Solo letras minúsculas, dígitos, _ y -; debe comenzar con una letra o dígito; hasta 64 caracteres.",
         invalidName: "Nombre de perfil no válido",
    -    cloneFromDefault: "Clonar configuración del perfil predeterminado",
    +    cloneFrom: "Clonar desde el perfil",
    +    cloneFromNone: "Ninguno (vacío)",
         allProfiles: "Perfiles",
         noProfiles: "No se encontraron perfiles.",
         defaultBadge: "predeterminado",
    ```
  - `web/src/i18n/fr.ts`

    ```diff
    @@ -287,7 +287,8 @@ export const fr: Translations = {
         nameRule:
           "Lettres minuscules, chiffres, _ et - uniquement ; doit commencer par une lettre ou un chiffre ; jusqu'à 64 caractères.",
         invalidName: "Nom de profil invalide",
    -    cloneFromDefault: "Cloner la configuration du profil par défaut",
    +    cloneFrom: "Cloner depuis le profil",
    +    cloneFromNone: "Aucun (vide)",
         allProfiles: "Profils",
         noProfiles: "Aucun profil trouvé.",
         defaultBadge: "défaut",
    ```
  - `web/src/i18n/ga.ts`

    ```diff
    @@ -294,8 +294,8 @@ export const ga: Translations = {
         nameRequired: "Tá ainm riachtanach",
         nameRule:
           "Litreacha cás íochtair, digití, _ agus - amháin; caithfidh tús a chur le litir nó digit; suas le 64 carachtar.",
    -    invalidName: "Ainm próifíle neamhbhailí",
    -    cloneFromDefault: "Clónáil cumraíocht ón bpróifíl réamhshocraithe",
    +    invalidName: "Ainm próifíle neamhbhailí",    cloneFrom: "Clónáil cumraíocht ón bpróifíl",
    +    cloneFromNone: "Dada (folamh)",
         allProfiles: "Próifílí",
         noProfiles: "Níor aimsíodh próifílí.",
         defaultBadge: "réamhshocraithe",
    ```
  - `web/src/i18n/hu.ts`

    ```diff
    @@ -286,8 +286,8 @@ export const hu: Translations = {
         nameRequired: "A név kötelező",
         nameRule:
           "Csak kisbetűk, számjegyek, _ és - karakterek; betűvel vagy számjeggyel kell kezdődnie; legfeljebb 64 karakter.",
    -    invalidName: "Érvénytelen profilnév",
    -    cloneFromDefault: "Konfiguráció klónozása az alapértelmezett profilból",
    +    invalidName: "Érvénytelen profilnév",    cloneFrom: "Konfiguráció klónozása ebből a profilból",
    +    cloneFromNone: "Nincs (üres)",
         allProfiles: "Profilok",
         noProfiles: "Nem található profil.",
         defaultBadge: "alapértelmezett",
    ```
  - `web/src/i18n/it.ts`

    ```diff
    @@ -286,8 +286,8 @@ export const it: Translations = {
         nameRequired: "Il nome è obbligatorio",
         nameRule:
           "Solo lettere minuscole, cifre, _ e -; deve iniziare con una lettera o cifra; fino a 64 caratteri.",
    -    invalidName: "Nome del profilo non valido",
    -    cloneFromDefault: "Clona la configurazione dal profilo predefinito",
    +    invalidName: "Nome del profilo non valido",    cloneFrom: "Clona configurazione dal profilo",
    +    cloneFromNone: "Nessuno (vuoto)",
         allProfiles: "Profili",
         noProfiles: "Nessun profilo trovato.",
         defaultBadge: "predefinito",
    ```
  - `web/src/i18n/ja.ts`

    ```diff
    @@ -285,8 +285,8 @@ export const ja: Translations = {
         nameRequired: "名前は必須です",
         nameRule:
           "小文字、数字、_ および - のみ使用可能。最初は文字または数字で始める必要があります。最大 64 文字。",
    -    invalidName: "無効なプロファイル名",
    -    cloneFromDefault: "デフォルトプロファイルから設定を複製",
    +    invalidName: "無効なプロファイル名",    cloneFrom: "プロファイルから複製",
    +    cloneFromNone: "なし（空）",
         allProfiles: "プロファイル",
         noProfiles: "プロファイルが見つかりません。",
         defaultBadge: "デフォルト",
    ```
  - `web/src/i18n/ko.ts`

    ```diff
    @@ -285,8 +285,8 @@ export const ko: Translations = {
         nameRequired: "이름은 필수입니다",
         nameRule:
           "소문자, 숫자, _ 및 - 만 사용 가능합니다. 문자나 숫자로 시작해야 하며 최대 64자입니다.",
    -    invalidName: "잘못된 프로필 이름입니다",
    -    cloneFromDefault: "기본 프로필에서 설정 복제",
    +    invalidName: "잘못된 프로필 이름입니다",    cloneFrom: "프로필에서 복제",
    +    cloneFromNone: "없음 (빈 상태)",
         allProfiles: "프로필",
         noProfiles: "프로필을 찾을 수 없습니다.",
         defaultBadge: "기본",
    ```
  - `web/src/i18n/pt.ts`

    ```diff
    @@ -287,7 +287,8 @@ export const pt: Translations = {
         nameRule:
           "Apenas letras minúsculas, dígitos, _ e -; deve começar com letra ou dígito; até 64 caracteres.",
         invalidName: "Nome de perfil inválido",
    -    cloneFromDefault: "Clonar configuração do perfil predefinido",
    +    cloneFrom: "Clonar a partir do perfil",
    +    cloneFromNone: "Nenhum (vazio)",
         allProfiles: "Perfis",
         noProfiles: "Não foram encontrados perfis.",
         defaultBadge: "predefinido",
    ```
  - `web/src/i18n/ru.ts`

    ```diff
    @@ -286,8 +286,8 @@ export const ru: Translations = {
         nameRequired: "Имя обязательно",
         nameRule:
           "Только строчные буквы, цифры, _ и -; должно начинаться с буквы или цифры; до 64 символов.",
    -    invalidName: "Недопустимое имя профиля",
    -    cloneFromDefault: "Клонировать конфигурацию из профиля по умолчанию",
    +    invalidName: "Недопустимое имя профиля",    cloneFrom: "Клонировать конфигурацию из профиля",
    +    cloneFromNone: "Нет (пусто)",
         allProfiles: "Профили",
         noProfiles: "Профили не найдены.",
         defaultBadge: "по умолчанию",
    ```
  - `web/src/i18n/tr.ts`

    ```diff
    @@ -286,8 +286,8 @@ export const tr: Translations = {
         nameRequired: "Ad gereklidir",
         nameRule:
           "Yalnızca küçük harfler, rakamlar, _ ve - kullanılabilir; harf veya rakamla başlamalı; en fazla 64 karakter.",
    -    invalidName: "Geçersiz profil adı",
    -    cloneFromDefault: "Varsayılan profilden yapılandırmayı klonla",
    +    invalidName: "Geçersiz profil adı",    cloneFrom: "Profilden yapılandırmayı klonla",
    +    cloneFromNone: "Hiçbiri (boş)",
         allProfiles: "Profiller",
         noProfiles: "Profil bulunamadı.",
         defaultBadge: "varsayılan",
    ```
  - `web/src/i18n/types.ts`

    ```diff
    @@ -354,7 +354,8 @@ export interface Translations {
         nameRequired: string;
         nameRule: string;
         invalidName: string;
    -    cloneFromDefault: string;
    +    cloneFrom: string;
    +    cloneFromNone: string;
         allProfiles: string;
         noProfiles: string;
         defaultBadge: string;
    ```
  - `web/src/i18n/uk.ts`

    ```diff
    @@ -287,7 +287,8 @@ export const uk: Translations = {
         nameRule:
           "Лише малі літери, цифри, _ та -; має починатися з літери або цифри; до 64 символів.",
         invalidName: "Недопустима назва профілю",
    -    cloneFromDefault: "Клонувати конфігурацію з профілю за замовчуванням",
    +    cloneFrom: "Клонувати з профілю",
    +    cloneFromNone: "Жоден (порожній)",
         allProfiles: "Профілі",
         noProfiles: "Профілів не знайдено.",
         defaultBadge: "за замовчуванням",
    ```
  - `web/src/i18n/zh-hant.ts`

    ```diff
    @@ -285,8 +285,8 @@ export const zhHant: Translations = {
         nameRequired: "名稱為必填",
         nameRule:
           "僅允許小寫字母、數字、底線及連字號；首字必須為字母或數字；最多 64 個字元。",
    -    invalidName: "設定檔名稱無效",
    -    cloneFromDefault: "從預設設定檔複製設定",
    +    invalidName: "設定檔名稱無效",    cloneFrom: "從設定檔複製",
    +    cloneFromNone: "無（空白）",
         allProfiles: "設定檔",
         noProfiles: "找不到設定檔。",
         defaultBadge: "預設",
    ```
  - `web/src/i18n/zh.ts`

    ```diff
    @@ -282,8 +282,8 @@ export const zh: Translations = {
         nameRequired: "名称必填",
         nameRule:
           "仅允许小写字母、数字、下划线和短横线；首字符必须是字母或数字；最多 64 个字符。",
    -    invalidName: "多Agent配置名称非法",
    -    cloneFromDefault: "从默认多Agent配置克隆配置",
    +    invalidName: "多Agent配置名称非法",    cloneFrom: "从配置文件克隆",
    +    cloneFromNone: "无（空白）",
         allProfiles: "多Agent配置列表",
         noProfiles: "暂无多Agent配置。",
         defaultBadge: "默认",
    ```
  - `web/src/lib/api.ts`

    ```diff
    @@ -552,7 +552,8 @@ export const api = {
         }),
       createProfile: (body: {
         name: string;
    -    clone_from_default: boolean;
    +    clone_from?: string | null;
    +    clone_from_default?: boolean;
         clone_all?: boolean;
         no_skills?: boolean;
         description?: string;
    ```
  - `web/src/pages/ProfileBuilderPage.tsx`

    ```diff
    @@ -220,7 +220,7 @@ export default function ProfileBuilderPage() {
         try {
           const res = await api.createProfile({
             name: n,
    -        clone_from_default: false,
    +        clone_from: null,
             description: description.trim() || undefined,
             provider: pickedModel?.provider,
             model: pickedModel?.model,
    ```
  - `web/src/pages/ProfilesPage.tsx`

    ```diff
    @@ -35,11 +35,11 @@ import { Badge } from "@nous-research/ui/ui/components/badge";
     import { Button } from "@nous-research/ui/ui/components/button";
     import { Input } from "@nous-research/ui/ui/components/input";
     import { Label } from "@nous-research/ui/ui/components/label";
    -import { Checkbox } from "@nous-research/ui/ui/components/checkbox";
     import {
       Select,
       SelectOption,
     } from "@nous-research/ui/ui/components/select";
    +import { Checkbox } from "@nous-research/ui/ui/components/checkbox";
     import { useI18n } from "@/i18n";
     import { usePageHeader } from "@/contexts/usePageHeader";
     import { cn, themedBody } from "@/lib/utils";
    ```

    ```diff
    @@ -312,7 +312,7 @@ export default function ProfilesPage() {
       // Create modal
       const [createModalOpen, setCreateModalOpen] = useState(false);
       const [newName, setNewName] = useState("");
    -  const [cloneFromDefault, setCloneFromDefault] = useState(true);
    +  const [cloneFrom, setCloneFrom] = useState<string | null>("default");
       const [cloneAll, setCloneAll] = useState(false);
       const [noSkills, setNoSkills] = useState(false);
       const [newDescription, setNewDescription] = useState("");
    ```

    ```diff
    @@ -429,7 +429,7 @@ export default function ProfilesPage() {
         }
         setCreating(true);
         try {
    -      const cloning = cloneAll || cloneFromDefault;
    +      const cloning = cloneFrom !== null;
           const picked = modelChoice
             ? modelChoices?.find(
                 (c) => `${c.provider}\u0000${c.model}` === modelChoice,
    ```

    ```diff
    @@ -437,8 +437,8 @@ export default function ProfilesPage() {
             : undefined;
           const res = await api.createProfile({
             name,
    -        clone_from_default: cloneAll ? false : cloneFromDefault,
    -        clone_all: cloneAll,
    +        clone_from: cloneFrom,
    +        clone_all: cloning && cloneAll,
             no_skills: cloning ? false : noSkills,
             description: newDescription.trim() || undefined,
             provider: picked?.provider,
    ```

    ```diff
    @@ -455,7 +455,7 @@ export default function ProfilesPage() {
           setNewDescription("");
           setNoSkills(false);
           setCloneAll(false);
    -      setCloneFromDefault(true);
    +      setCloneFrom("default");
           setModelChoice("");
           setCreateModalOpen(false);
           load();
    ```

    ```diff
    @@ -772,7 +772,7 @@ export default function ProfilesPage() {
         };
       }, [setEnd, t.common.create, loading, navigate]);
     
    -  const cloning = cloneAll || cloneFromDefault;
    +  const cloning = cloneFrom !== null;
     
       if (loading) {
         return (
    ```

    ```diff
    @@ -862,6 +862,26 @@ export default function ProfilesPage() {
                     </p>
                   </div>
     
    +              <div className="grid gap-2">
    +                <Label htmlFor="clone-from">{t.profiles.cloneFrom}</Label>
    +                <Select
    +                  id="clone-from"
    +                  value={cloneFrom ?? ""}
    +                  onValueChange={(v) => {
    +                    const next = v || null;
    +                    setCloneFrom(next);
    +                    if (next === null) setCloneAll(false);
    +                  }}
    +                >
    +                  <SelectOption value="">{t.profiles.cloneFromNone}</SelectOption>
    +                  {profiles.map((profile) => (
    +                    <SelectOption key={profile.name} value={profile.name}>
    +                      {profile.name}
    +                    </SelectOption>
    +                  ))}
    +                </Select>
    +              </div>
    +
                   <div className="grid gap-2">
                     <Label htmlFor="profile-description">
                       {L.descriptionOptional}
    ```

    ```diff
    @@ -909,33 +929,19 @@ export default function ProfilesPage() {
                       {L.advancedOptions}
                     </legend>
     
    -                <div className="flex items-center gap-2.5">
    -                  <Checkbox
    -                    checked={cloneFromDefault}
    -                    id="clone-from-default"
    -                    disabled={cloneAll}
    -                    onCheckedChange={(checked) =>
    -                      setCloneFromDefault(checked === true)
    -                    }
    -                  />
    -
    -                  <Label
    -                    className="font-mondwest normal-case tracking-normal text-sm cursor-pointer"
    -                    htmlFor="clone-from-default"
    -                  >
    -                    {t.profiles.cloneFromDefault}
    -                  </Label>
    -                </div>
    -
                     <div className="flex items-center gap-2.5">
                       <Checkbox
                         checked={cloneAll}
    +                    disabled={!cloning}
                         id="clone-all"
                         onCheckedChange={(checked) => setCloneAll(checked === true)}
                       />
     
                       <Label
    -                    className="font-mondwest normal-case tracking-normal text-sm cursor-pointer"
    +                    className={cn(
    +                      "font-mondwest normal-case tracking-normal text-sm cursor-pointer",
    +                      !cloning && "opacity-50",
    +                    )}
                         htmlFor="clone-all"
                       >
                         {L.cloneAll}
    ```
  - `website/docs/reference/cli-commands.md`

    ```diff
    @@ -1396,7 +1396,7 @@ Manage profiles — multiple isolated Hermes instances, each with its own config
     |------------|-------------|
     | `list` | List all profiles. |
     | `use <name>` | Set a sticky default profile. |
    -| `create <name> [--clone] [--clone-all] [--clone-from <source>] [--no-alias]` | Create a new profile. `--clone` copies config, `.env`, and `SOUL.md` from the active profile. `--clone-all` copies all state. `--clone-from` specifies a source profile. |
    +| `create <name> [--clone] [--clone-all] [--clone-from <source>] [--no-alias]` | Create a new profile. `--clone` copies config, `.env`, `SOUL.md`, and skills from the active profile. `--clone-all` copies all state. `--clone-from` specifies a source profile and implies config clone unless paired with `--clone-all`. |
     | `delete <name> [-y]` | Delete a profile. |
     | `show <name>` | Show profile details (home directory, config, etc.). |
     | `alias <name> [--remove] [--name NAME]` | Manage wrapper scripts for quick profile access. |
    ```
  - `website/docs/reference/faq.md`

    ```diff
    @@ -634,7 +634,7 @@ No. Each messaging platform (Telegram, Discord, etc.) requires exclusive access
     
     ### Do profiles share memory or sessions?
     
    -No. Each profile has its own memory store, session database, and skills directory. They are completely isolated. If you want to start a new profile with existing memories and sessions, use `hermes profile create newname --clone-all` to copy everything from the current profile.
    +No. Each profile has its own memory store, session database, and skills directory. They are completely isolated. If you want to start a new profile with existing memories and sessions, use `hermes profile create newname --clone-all` to copy everything from the current profile, or add `--clone-from <profile>` to copy from a specific source profile.
     
     ### What happens when I run `hermes update`?
     
    ```
  - `website/docs/reference/profile-commands.md`

    ```diff
    @@ -80,12 +80,12 @@ Creates a new profile.
     | Argument / Option | Description |
     |-------------------|-------------|
     | `<name>` | Name for the new profile. Must be a valid directory name (alphanumeric, hyphens, underscores). |
    -| `--clone` | Copy `config.yaml`, `.env`, and `SOUL.md` from the current profile. |
    +| `--clone` | Copy `config.yaml`, `.env`, `SOUL.md`, and skills from the current profile. |
     | `--clone-all` | Copy everything (config, memories, skills, cron, plugins) from the current profile. Excludes per-profile history: sessions, `state.db`, backups, state-snapshots, checkpoints. |
    -| `--clone-from <profile>` | Clone from a specific profile instead of the current one. Used with `--clone` or `--clone-all`. |
    +| `--clone-from <profile>` | Clone config/skills/SOUL from a specific profile instead of the current one. Implies `--clone` unless paired with `--clone-all`. |
     | `--no-alias` | Skip wrapper script creation. |
     | `--description "<text>"` | One- or two-sentence description of what this profile is good at. Used by the kanban orchestrator to route tasks based on role instead of profile name alone. Skip and add later via `hermes profile describe`. Persisted in `<profile_dir>/profile.yaml`. |
    -| `--no-skills` | Create an **empty** profile with zero bundled skills enabled. Writes a `.no-bundled-skills` marker into the profile so future `hermes update` runs won't re-seed the bundled set, and refuses to combine with `--clone` / `--clone-all` (which would copy skills in anyway). Useful for narrow orchestrator profiles or sandbox profiles that should not inherit the full skill catalog. To toggle this on an already-created profile (including the default `~/.hermes`), use `hermes skills opt-out` / `hermes skills opt-in`. |
    +| `--no-skills` | Create an **empty** profile with zero bundled skills enabled. Writes a `.no-bundled-skills` marker into the profile so future `hermes update` runs won't re-seed the bundled set, and refuses to combine with `--clone`, `--clone-from`, or `--clone-all` (which would copy skills in anyway). Useful for narrow orchestrator profiles or sandbox profiles that should not inherit the full skill catalog. To toggle this on an already-created profile (including the default `~/.hermes`), use `hermes skills opt-out` / `hermes skills opt-in`. |
     
     Creating a profile does **not** make that profile directory the default project/workspace directory for terminal commands. If you want a profile to start in a specific project, set `terminal.cwd` in that profile's `config.yaml`.
     
    ```

    ```diff
    @@ -102,7 +102,10 @@ hermes profile create work --clone
     hermes profile create backup --clone-all
     
     # Clone config from a specific profile
    -hermes profile create work2 --clone --clone-from work
    +hermes profile create work2 --clone-from work
    +
    +# Clone everything from a specific profile
    +hermes profile create work2-backup --clone-from work --clone-all
     ```
     
     ## `hermes profile describe`
    ```
  - `website/docs/user-guide/profiles.md`

    ```diff
    @@ -50,7 +50,7 @@ You can also set or auto-generate the description later with `hermes profile des
     hermes profile create work --clone
     ```
     
    -Copies your current profile's `config.yaml`, `.env`, and `SOUL.md` into the new profile. Same API keys and model, but fresh sessions and memory. Edit `~/.hermes/profiles/work/.env` for different API keys, or `~/.hermes/profiles/work/SOUL.md` for a different personality.
    +Copies your current profile's `config.yaml`, `.env`, `SOUL.md`, and skills into the new profile. Same API keys, model, and capabilities, but fresh sessions and memory. Edit `~/.hermes/profiles/work/.env` for different API keys, or `~/.hermes/profiles/work/SOUL.md` for a different personality.
     
     ### Clone everything (`--clone-all`)
     
    ```

    ```diff
    @@ -63,11 +63,17 @@ Copies **everything** — config, API keys, personality, all memories, skills, c
     ### Clone from a specific profile
     
     ```bash
    -hermes profile create work --clone --clone-from coder
    +hermes profile create work --clone-from coder
    +```
    +
    +`--clone-from <source>` selects the source profile directly and implies a config/skills/SOUL clone. Combine it with `--clone-all` when you want a full copy of that source profile:
    +
    +```bash
    +hermes profile create work-backup --clone-from coder --clone-all
     ```
     
     :::tip Honcho memory + profiles
    -When Honcho is enabled, `--clone` automatically creates a dedicated AI peer for the new profile while sharing the same user workspace. Each profile builds its own observations and identity. See [Honcho -- Multi-agent / Profiles](./features/memory-providers.md#honcho) for details.
    +When Honcho is enabled, clone operations automatically create a dedicated AI peer for the new profile while sharing the same user workspace. Each profile builds its own observations and identity. See [Honcho -- Multi-agent / Profiles](./features/memory-providers.md#honcho) for details.
     :::
     
     ## Using profiles
    ```
  - `website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/cli-commands.md`

    ```diff
    @@ -1175,7 +1175,7 @@ hermes profile <subcommand>
     |------------|-------------|
     | `list` | 列出所有 profile。 |
     | `use <name>` | 设置粘性默认 profile。 |
    -| `create <name> [--clone] [--clone-all] [--clone-from <source>] [--no-alias]` | 创建新 profile。`--clone` 从活跃 profile 复制 config、`.env` 和 `SOUL.md`。`--clone-all` 复制所有状态。`--clone-from` 指定源 profile。 |
    +| `create <name> [--clone] [--clone-all] [--clone-from <source>] [--no-alias]` | 创建新 profile。`--clone` 从活跃 profile 复制 config、`.env`、`SOUL.md` 和 skills。`--clone-all` 复制所有状态。`--clone-from` 指定源 profile，除非与 `--clone-all` 配合使用，否则会隐含 config 克隆。 |
     | `delete <name> [-y]` | 删除 profile。 |
     | `show <name>` | 显示 profile 详情（主目录、config 等）。 |
     | `alias <name> [--remove] [--name NAME]` | 管理快速访问 profile 的包装脚本。 |
    ```
  - `website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/faq.md`

    ```diff
    @@ -626,7 +626,7 @@ Profiles 是构建在 `HERMES_HOME` 之上的托管层。您*可以*在每次命
     
     ### Profiles 共享记忆或会话吗？
     
    -不共享。每个 profile 都有自己独立的记忆存储、会话数据库和技能目录，完全隔离。如果您想用现有的记忆和会话创建新 profile，请使用 `hermes profile create newname --clone-all` 从当前 profile 复制所有内容。
    +不共享。每个 profile 都有自己独立的记忆存储、会话数据库和技能目录，完全隔离。如果您想用现有的记忆和会话创建新 profile，请使用 `hermes profile create newname --clone-all` 从当前 profile 复制所有内容，或添加 `--clone-from <profile>` 从指定源 profile 复制。
     
     ### 运行 `hermes update` 时会发生什么？
     
    ```
  - `website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/profile-commands.md`

    ```diff
    @@ -79,12 +79,12 @@ hermes profile create <name> [options]
     | 参数 / 选项 | 描述 |
     |-------------------|-------------|
     | `<name>` | 新 profile 的名称。必须是合法的目录名（字母数字、连字符、下划线）。 |
    -| `--clone` | 从当前 profile 复制 `config.yaml`、`.env` 和 `SOUL.md`。 |
    -| `--clone-all` | 从当前 profile 复制所有内容（config、memories、skills、sessions、state）。 |
    -| `--clone-from <profile>` | 从指定 profile 克隆，而非当前 profile。与 `--clone` 或 `--clone-all` 配合使用。 |
    +| `--clone` | 从当前 profile 复制 `config.yaml`、`.env`、`SOUL.md` 和 skills。 |
    +| `--clone-all` | 从当前 profile 复制所有内容（config、memories、skills、cron、plugins）。会排除每个 profile 自己的历史数据：sessions、`state.db`、backups、state-snapshots、checkpoints。 |
    +| `--clone-from <profile>` | 从指定 profile 克隆 config/skills/SOUL，而非当前 profile。除非与 `--clone-all` 配合使用，否则会隐含 `--clone`。 |
     | `--no-alias` | 跳过 wrapper 脚本创建。 |
     | `--description "<text>"` | 一到两句话描述该 profile 的用途。供 kanban 编排器根据角色而非仅凭 profile 名称来路由任务。可跳过，稍后通过 `hermes profile describe` 添加。持久化保存在 `<profile_dir>/profile.yaml` 中。 |
    -| `--no-skills` | 创建一个**空** profile，不启用任何内置 skill。会在 profile 目录中写入 `.no-skills` 标记，使后续 `hermes update` 不再重新植入内置 skill 集，且拒绝与 `--clone` / `--clone-all` 组合使用（因为后者会复制 skill）。适用于不应继承完整 skill 目录的窄化编排器 profile 或沙箱 profile。 |
    +| `--no-skills` | 创建一个**空** profile，不启用任何内置 skill。会在 profile 目录中写入 `.no-bundled-skills` 标记，使后续 `hermes update` 不再重新植入内置 skill 集，且拒绝与 `--clone`、`--clone-from` 或 `--clone-all` 组合使用（因为这些选项会复制 skill）。适用于不应继承完整 skill 目录的窄化编排器 profile 或沙箱 profile。 |
     
     创建 profile **不会**将该 profile 目录设为终端命令的默认项目/工作目录。如需让某个 profile 从特定项目目录启动，请在该 profile 的 `config.yaml` 中设置 `terminal.cwd`。
     
    ```

    ```diff
    @@ -101,7 +101,10 @@ hermes profile create work --clone
     hermes profile create backup --clone-all
     
     # 从指定 profile 克隆 config
    -hermes profile create work2 --clone --clone-from work
    +hermes profile create work2 --clone-from work
    +
    +# 从指定 profile 克隆所有内容
    +hermes profile create work2-backup --clone-from work --clone-all
     ```
     
     ## `hermes profile describe`
    ```
  - `website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/profiles.md`

    ```diff
    @@ -46,7 +46,7 @@ hermes profile create researcher --description "Reads source code and external d
     hermes profile create work --clone
     ```
     
    -将当前 profile 的 `config.yaml`、`.env` 和 `SOUL.md` 复制到新 profile。API 密钥和模型相同，但会话和记忆是全新的。编辑 `~/.hermes/profiles/work/.env` 可使用不同的 API 密钥，编辑 `~/.hermes/profiles/work/SOUL.md` 可设置不同的人格。
    +将当前 profile 的 `config.yaml`、`.env`、`SOUL.md` 和 skills 复制到新 profile。API 密钥、模型和能力相同，但会话和记忆是全新的。编辑 `~/.hermes/profiles/work/.env` 可使用不同的 API 密钥，编辑 `~/.hermes/profiles/work/SOUL.md` 可设置不同的人格。
     
     ### 克隆全部内容（`--clone-all`）
     
    ```

    ```diff
    @@ -54,16 +54,22 @@ hermes profile create work --clone
     hermes profile create backup --clone-all
     ```
     
    -复制**所有内容**——配置、API 密钥、人格、所有记忆、完整会话历史、技能、cron 任务、插件。完整快照。适用于备份或 fork 已有上下文的 agent。
    +复制**所有内容**——配置、API 密钥、人格、记忆、技能、cron 任务、插件。会排除每个 profile 自己的历史数据（会话历史、`state.db`、`backups/`、`state-snapshots/`、`checkpoints/`），这些数据属于源 profile 且可能达到数十 GB。若要包含历史的完整备份，请使用 `hermes profile export` 或 `hermes backup`。
     
     ### 从指定 profile 克隆
     
     ```bash
    -hermes profile create work --clone --clone-from coder
    +hermes profile create work --clone-from coder
    +```
    +
    +`--clone-from <source>` 会直接选择源 profile，并隐含执行 config/skills/SOUL 克隆。若要完整复制该源 profile，请与 `--clone-all` 组合使用：
    +
    +```bash
    +hermes profile create work-backup --clone-from coder --clone-all
     ```
     
     :::tip Honcho 记忆 + profiles
    -启用 Honcho 后，`--clone` 会自动为新 profile 创建专属 AI 对等体，同时共享同一用户工作区。每个 profile 构建各自的观察记录和身份标识。详见 [Honcho——多 agent / Profiles](./features/memory-providers.md#honcho)。
    +启用 Honcho 后，克隆操作会自动为新 profile 创建专属 AI 对等体，同时共享同一用户工作区。每个 profile 构建各自的观察记录和身份标识。详见 [Honcho——多 agent / Profiles](./features/memory-providers.md#honcho)。
     :::
     
     ## 使用 profile
    ```
- **#45558: feat(dashboard): clone new profile from any profile (dropdown instead of checkbox)**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#45630`

## Fix status

- Merged to main in PR #45630 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-13`.
- Subsystem: `hermes_cli`
