From narnia
Create, migrate, move, share, and manage Narnia-owned scheduled Copilot jobs — recurring `copilot -p` runs that Windows Task Scheduler executes unattended on a daily/weekly/monthly cadence. Use to schedule a new recurring job, migrate an existing hand-built Windows Scheduled Task into Narnia, export/import portable schedule packages between computers or users, run a supervised dry-run before trusting a schedule, or inspect/enable/disable/run/delete a cataloged job.
How this skill is triggered — by the user, by Claude, or both
Slash command
/narnia:narnia-schedulerThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create, migrate, move, share, and manage Narnia-owned scheduled Copilot jobs — recurring
Create, migrate, move, share, and manage Narnia-owned scheduled Copilot jobs — recurring
copilot -p runs that Windows Task Scheduler executes unattended on a daily/weekly/monthly cadence.
This skill is the workflow layer on top of Narnia's schedule and package MCP tools, which are already
available as regular tool calls in any session sharing Narnia's MCP endpoint.
.narnia-schedules.json package.create_schedule/update_schedule generate a self-contained wrapper script
under Narnia's own app-data folder and register/refresh the OS task; they never touch a user's own
scripts.create_schedule owns its generated wrapper and can always be edited
later with update_schedule. Never invent a second tier of jobs that aren't fully editable.copilot -p <prompt> with NO pre-injected environment. Whatever a
prompt/skill needs (database connections, API keys, SMTP credentials, ...) must be self-resolved by
the skill/script itself (e.g. read a repo .env) — never assume a wrapper will inject it. See
Writing a self-contained prompt below.copilot. The wrapper already IS the copilot -p invocation. The prompt should
never itself try to spawn another copilot call; deterministic follow-up work (a database write,
an email, a git commit) belongs in a plain script that the prompt calls directly.settings.db,
Task Scheduler XML, generated run.ps1/run.vbs, logs, Copilot sessions, or source job folders.
The destination regenerates all of those locally..env contents, tokens, SMTP values, or database passwords.
Package creation rejects obvious credential-like literals; if it does, move that value into
destination-local configuration instead of weakening or bypassing the check.import_schedule_package creates new local Narnia ids and
atomically disabled Task Scheduler entries. Never enable an imported job until its dependencies,
rendered prompt, and supervised dry run have been reviewed.| Tool | Purpose |
|---|---|
list_schedules | All cataloged jobs joined to live Task Scheduler status, plus untracked \Narnia\ tasks |
get_schedule | A single job's full catalog entry (including its prompt) by id |
create_schedule | Create a job: generate the wrapper, and (by default) register the OS task |
update_schedule | Replace a job's definition, regenerate its wrapper, re-register in place |
set_schedule_enabled | Enable/disable a job's OS task without deleting it |
run_schedule_now | Start a job's OS task immediately, out of band from its cadence |
delete_schedule | Remove a job's OS task, wrapper, and catalog entry (irreversible) |
export_schedule_package | Export selected Narnia jobs as a transfer package or share template |
build_schedule_package | Package canonical definitions reconstructed from non-Narnia tasks |
preview_schedule_package | Resolve bindings and inspect conflicts/dependencies without side effects |
import_schedule_package | Materialize an accepted preview as new disabled Narnia jobs |
These are already available as normal tool calls — do not shell out to an HTTP API or the web UI to do what these tools do directly.
cadenceKind = daily | weekly | monthly, a 24-hour time, and either
days (weekly, day names) or dayOfMonth (monthly, 1-31).create_schedule with register: true (the default) so the OS task is created now. Use
register: false only if the user wants to review the generated script before installing it, or
is on a platform where registration isn't supported — you'll get back script + command to hand
to the user instead.get_schedule (or list_schedules) and confirm taskFound: true, a sane
nextRunTime, and state: "ready".\Narnia\
tasks):
& "<skill-dir>/scripts/Read-ExistingScheduledTask.ps1" -TaskName "<name>" -TaskPath "<folder>"
This returns one object per trigger with a SuggestedCadence (cadenceKind/time/days/dayOfMonth/cwd)
ready to hand to create_schedule, plus ResolvedScriptPath if the task's action runs a script.
create_schedule call per
supported trigger (a job has exactly one cadence). This mirrors how a task with separate Weekly
and Monthly triggers should become two Narnia jobs, not one.TriggerSupported: false means the trigger has no Narnia equivalent (a one-off Once
trigger, or a boot/logon/idle/event trigger) — tell the user this one can't be migrated as-is.copilot -p job will NOT have.create_schedule with the suggested cadence and your new prompt (register: true).get_schedule/list_schedules) and, ideally, run a supervised dry run
(below) before trusting it.Disable-ScheduledTask -TaskName "<name>" -TaskPath "<folder>"
Keep it as a backup until the new job has completed at least one real unattended run.list_schedules and identify the exact job ids.transfer: moving work between machines they control; retains non-secret source path hints.share: sending a reusable template to someone else; removes source-local hints and identity.export_schedule_package with every selected id in one request.packageJson to a .narnia-schedules.json file in the current Copilot session
workspace and return its absolute path. Do not hand-edit generated fingerprints.Generated wrappers, task XML, logs, task history, and the Narnia settings database are intentionally absent. The destination will generate new local ids, scripts, and task registrations.
& "<skill-dir>/scripts/Find-CopilotScheduledTasks.ps1" | Format-Table -AutoSize
It does not read wrapper contents or modify tasks. Let the user identify the intended tasks.Read-ExistingScheduledTask.ps1 for each selected task and trigger.ResolvedScriptPath is present, read only that selected script. Determine:
ScheduledJobDefinition for every supported trigger. Multiple
triggers remain separate package jobs.build_schedule_package, including every identified configuration or omitted external-state
requirement in its dependencies array; do not create a temporary local Narnia schedule first.packageJson as a .narnia-schedules.json artifact.preview_schedule_package with empty bindings/jobs arrays and
no guessed values.canImport: true. Review timezone warnings, broad allow flags, the rendered prompt, and any
omitted external state.import_schedule_package with the unchanged package JSON, identical bindings/options, and
the latest preview fingerprint.set_schedule_enabled.A job's prompt runs under a plain copilot -p with no pre-injected environment. Before calling
create_schedule, check:
.env — rather than assuming an
environment variable is already set. A proven pattern: read the file, split each line on the
first =, and strip one matching pair of surrounding quotes (single OR double — code that
only strips double quotes will silently keep a single-quoted secret quoted and fail to connect;
this is a real bug that has shipped before). Only set a variable if it isn't already set, so an
explicit environment always wins.copilot. The prompt should never itself invoke copilot -p — it's already
running inside one. Deterministic follow-up (a DB write, an email, a git commit) is a plain
script the prompt calls directly, colocated with the skill it belongs to.cwd) whenever the prompt depends on a repo-local skill (a skill
only available because Copilot was launched from that repo's directory) — check whether the
skill is a globally-installed plugin or repo-local, and set cwd accordingly for the latter../drafts/, then run scriptname.ps1 -DraftPath <path> for the deterministic
follow-up." There is no hidden wrapper behavior beyond what the prompt says.narnia-report-email skill after the report exists. Name the profile and subject in the
prompt, state whether zero-finding reports should still be sent, and treat delivery failure as
job failure. Never add SMTP values to the schedule wrapper or prompt.Use the narnia-report-email skill when a scheduled job should deliver a generated Markdown
artifact. It resolves its own SMTP profile from Narnia's LocalAppData folder and has a network-free
render-only mode for supervised validation.
Run the report-producing skill and write the final Markdown report to an absolute path in the
current Copilot session workspace. If report generation fails, stop and report the failure.
After the report file exists, invoke the narnia-report-email skill with that report path, profile
"default", and subject "Weekly engineering report". Send the email even when the report contains
zero findings. Treat any email-delivery error as a failed job. Do not print or request SMTP
credentials.
Before letting a new schedule run unattended for the first time, run its generation logic manually with the bundled dry-run helper, ideally with the real secrets scrubbed from the environment so the run proves self-resolution actually works (not that your current shell happens to already have the right variables set):
& "<skill-dir>/scripts/Invoke-NarniaDryRun.ps1" `
-Cwd "C:\dev\example-repo" `
-ScrubEnvPrefix "EXAMPLE_" `
-Prompt "Generate ... using the example skill. Do NOT write to the database, do NOT send email, do NOT git commit or push -- produce only the local draft file and print its absolute path as the final line."
This only proves the generation half is self-contained. If the job also runs deterministic follow-up (DB write, email), test that separately, with the write/email steps guarded behind an explicit flag the way the original design intended (default off; the scheduled invocation turns it on deliberately) rather than trying to make the dry-run script guess what's safe.
.Trim('"')-only quote-strip pattern. If a secret value in a .env file is
single-quoted, stripping only double quotes leaves the value still quoted and breaks the
connection string. Strip a matching pair of either quote character..Triggers CIM data for a migrated task's monthly schedule. A calendar trigger
registered via raw task XML (as Narnia itself does for monthly, since New-ScheduledTaskTrigger has
no monthly option) can read back as a generic, detail-less trigger through the ScheduledTasks
module's CIM collection. Read-ExistingScheduledTask.ps1 reads the exported XML instead for exactly
this reason — trust its output over a manual Get-ScheduledTask .Triggers inspection.create_schedule/update_schedule with register: true require Windows Task
Scheduler. list_schedules/get_schedule report schedulerSupported: false on unsupported
platforms; use register: false to get a copy-paste script + command instead.npx claudepluginhub ncosentino/narnia --plugin narniaGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.