# Jael Examples

This documents contains practical examples of a number of Jael's tasks.

General documentation of the tasks demonstrated here can be found in the [API Reference](/urbit-os/kernel/jael/tasks.md) document, and details of the data types mentioned can be found in the [Data Types](/urbit-os/kernel/jael/data-types.md) document.

## `%private-keys` <a href="#private-keys" id="private-keys"></a>

Here we'll look at subscribing to private key updates from Jael. We'll use a thread to pass Jael a `%private-keys` task, take the `%private-keys` gift it returns, debug print it to the terminal and finally unsubscribe with a `%nuke` task.

`sub-priv.hoon`

```hoon
/-  spider
/+  strandio
=,  strand=strand:spider
=,  card=card:agent:gall
^-  thread:spider
|=  arg=vase
=/  m  (strand ,vase)
^-  form:m
;<  ~  bind:m  (send-raw-card:strandio %pass /sub-priv %arvo %j %private-keys ~)
;<  res=[=wire =sign-arvo]  bind:m  take-sign-arvo:strandio
?>  ?=([%sub-priv ~] wire.res)
?>  ?=([%jael *] sign-arvo.res)
~&  +.sign-arvo.res
;<  ~  bind:m  (send-raw-card:strandio %pass /sub-priv %arvo %j %nuke ~)
(pure:m !>(~))
```

Save the above thread in the `/ted` directory of your `%base` desk and `|commit %base`.

Now let's run the thread:

```
> -sub-priv
```

You should see the `%private-key` gift it returns in the Dojo:

```
[ %private-keys
  life=1
    vein
  { [ p=1
        q
      1.729.646.917.183.337.[...truncated for brevity]
    ]
  }
]
```

At this point our thread unsubscribes again with a `%nuke` task but without that it would send a new `%private-key` gift each time the private keys were changed.

## `%public-keys` and `%nuke` <a href="#public-keys-and-nuke" id="public-keys-and-nuke"></a>

Here we'll look at both subscribing and unsubscribing to updates of a ship's public keys in Jael. We'll subscribe by sending Jael a `%public-keys` task, take the `%public-keys` gift it responds with, print it to the terminal, scry for the `+set` of `$duct`s subscribed to the ship in question, print them to the terminal, and finally send Jael a `%nuke` task to unsubscribe.

Here's a thread that performs these actions:

`sub-pub.hoon`

```hoon
/-  spider
/+  strandio
=,  strand=strand:spider
=,  card=card:agent:gall
=>
|%
+$  subs
  $:  yen=(jug duct ship)
      ney=(jug ship duct)
      nel=(set duct)
  ==
--
^-  thread:spider
|=  arg=vase
=/  m  (strand ,vase)
^-  form:m
=/  =@p  (need !<((unit @p) arg))
::
::  sub to public updates for specified ship
=/  c1=card  [%pass /sub-pubkeys %arvo %j %public-keys (silt ~[p])]
;<  ~  bind:m  (send-raw-card:strandio c1)
::
::  take response from jael & print it
;<  res=[=wire =sign-arvo]  bind:m  take-sign-arvo:strandio
?>  ?=([%sub-pubkeys ~] wire.res)
?>  ?=([%jael %public-keys *] sign-arvo.res)
~&  +.sign-arvo.res
::
::  scry for tracking subs for specified ship in jael & print
;<  =subs  bind:m  (scry:strandio ,subs /j/subscriptions/1)
=/  ducts=(set duct)  (~(get ju ney.subs) p)
~&  ducts
::
::  unsub from public updates for specified ships
=/  c2=card  [%pass /sub-pubkeys %arvo %j %nuke (silt ~[p])]
;<  ~  bind:m  (send-raw-card:strandio c2)
(pure:m !>(~))
```

Note this example was performed on a comet as a fake ship won't have the required information in Jael.

Save the above thread in the `/ted` directory and `|commit %base`. The thread takes a `$ship` as an argument, so we'll try to subscribe to pubkey updates for `~dopzod`. Let's run the thread:

```
> -sub-pub ~dopzod
```

It first passes a `%public-keys` task to Jael that looks like `[%public-keys (silt ~[~dopzod])]` in order to subscribe. Jael will immediately respond with a `%public-keys` gift that contains a `%full` [`$public-keys-result`](/urbit-os/kernel/jael/data-types.md#public-keys-result). The `(map ship point)` contained will (for each ship specified in the task) include the current pubkeys for the ship's current life as well as previous keys for previous `$life`s. It thus contains a complete record of keys up to the present for each ship. Our thread will print these out to the terminal like so:

```
[ %public-keys
    public-keys-result
  [ %full
      points
    { [ p=~dopzod
          q
        [ rift=2
          life=3
            keys
          { [ p=1
                q
              [ crypto-suite=1
                  pass
                939.529.329.928[...truncated for brevity...]
              ]
            ]
            [ p=2
                q
              [ crypto-suite=1
                  pass
                2.215.774.809.906.200.376.0[...truncated for brevity...]
              ]
            ]
            [ p=3
                q
              [ crypto-suite=1
                  pass
                707.070.568.606.374.[...truncated for brevity...]
              ]
            ]
          }
          sponsor=~
        ]
      ]
    }
  ]
]
```

Along with giving us the current information, Jael will also subscribe us to any future updates for the ships in question. Such updates will come as additional `%public-keys` gifts, but rather than a `%full` `$public-keys-result`, they'll instead contain either a `%diff` or `%breach` `$public-keys-result`, depending on what's happened to the ship in question. It's difficult to simulate such events for demonstrative purposes so an example is not included, but you can look at the [`$public-keys-result`](/urbit-os/kernel/jael/data-types.md#public-keys-result) to get an idea.

Jael maintains a `(jug duct ship)` and its reverse `(jug ship duct)` in its state to track subscriptions. If we do a [subscriptions](/urbit-os/kernel/jael/scry.md#subscriptions) scry and filter the result for `~dopzod`, we can see the duct of our thread has now been added to the `~dopzod` `+set`. Our thread does this, and will output something like:

```
{~[/gall/use/spider/0w1.vGVi-/~sampel-palnet/thread/~.dojo_0v6.0hlak.dam1b.bcdou.ai7gq.19fi8/sub-pubkeys /dill //term/1]}
```

At this point our thread will send a `%nuke` task like `[%nuke (silt ~[~dopzod])]` to cancel our subscription. Jael doesn't respond to it, but now, with our thread having finished and exited, we can again scry & filter for subscriptions to `~dopzod`:

```
> =/(a .^([yen=(jug duct ship) ney=(jug ship duct) nel=(set duct)] %j /=subscriptions=/1) (~(get ju ney.a) ~dopzod))
~
```

As you can see the `+set` is now empty, so we know the `%nuke` succeeded and Jael will no longer send us pubkey updates for `~dopzod`. One thing to note about `%nuke` is that it *must* come from the same `$duct` as the original subscription. You can't unsubscribe another app, ship, thread or what have you, so if we'd tried `%nuke`ing the subscription from a separate thread it wouldn't have worked.

## `%turf` <a href="#turf" id="turf"></a>

Here we'll look at using a `%turf` task to get Jael's list of domains. Note on a fake ship the list will be empty, so you may wish to run it on a comet or moon.

Here's a simple thread that'll pass Jael a `%turf` task, take the `%turf` gift it sends back and print it to the terminal:

`turf.hoon`

```hoon
/-  spider
/+  strandio
=,  strand=strand:spider
^-  thread:spider
|=  arg=vase
=/  m  (strand ,vase)
^-  form:m
=/  =task:jael  [%turf ~]
=/  =card:agent:gall  [%pass /get-domains %arvo %j task]
;<  ~  bind:m  (send-raw-card:strandio card)
;<  resp=[=wire =sign-arvo]  bind:m  take-sign-arvo:strandio
?>  ?=([%get-domains ~] wire.resp)
?>  ?=([%jael %turf *] sign-arvo.resp)
~&  +.sign-arvo.resp
(pure:m !>(~))
```

Save in in the `/ted` directory of your ship and `|commit %base`. Next, let's try running it:

```
> -turf
[%turf turf=~[<|org urbit|>]]
```

As you see, the `%turf` gift contains `urbit.org` as `~['org' 'urbit']`.

## `%step` <a href="#step" id="step"></a>

Here we'll look at changing the web login code with a `%step` task.

First, let's see the current `step` with a `%step` scry:

```
> .^(@ud %j /=step=/(scot %p our))
0
```

...and the current code with the `+code` generator:

```
> +code
lidlut-tabwed-pillex-ridrup
```

Now, let's pass Jael a `%step` task by using `|pass` in the dojo:

```
> |pass [%j %step ~]
```

Jael will `+pass` Eyre a `%code-changed` task to let Eyre know the code's changed so you'll see a message from Eyre in the terminal:

```
eyre: code-changed: throwing away cookies and sessions
```

Now let's again scry for the `+step` and see that it's been incremented:

```
> .^(@ud %j /=step=/(scot %p our))
1
```

And finally, let's again run `+code` and see there's now a new web login code:

```
> +code
raldev-topnul-mirnut-lablut
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.urbit.org/urbit-os/kernel/jael/examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
